diff --git a/1.2/404.html b/1.2/404.html new file mode 100644 index 000000000..5c9d4c54e --- /dev/null +++ b/1.2/404.html @@ -0,0 +1,1432 @@ + + + + + + + + + + + + + + + + + + + Crow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + + +
+ +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + + +
+ +
+ + + + + + + + + + +
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/1.2/assets/crowlogo.svg b/1.2/assets/crowlogo.svg new file mode 100644 index 000000000..e33d0f75d --- /dev/null +++ b/1.2/assets/crowlogo.svg @@ -0,0 +1,127 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/1.2/assets/crowlogo_dual_color.svg b/1.2/assets/crowlogo_dual_color.svg new file mode 100644 index 000000000..b70a954c6 --- /dev/null +++ b/1.2/assets/crowlogo_dual_color.svg @@ -0,0 +1,90 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/1.2/assets/crowlogo_inverted.svg b/1.2/assets/crowlogo_inverted.svg new file mode 100644 index 000000000..2784f9c50 --- /dev/null +++ b/1.2/assets/crowlogo_inverted.svg @@ -0,0 +1,121 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/1.2/assets/crowlogo_main_color.svg b/1.2/assets/crowlogo_main_color.svg new file mode 100644 index 000000000..5929a8b91 --- /dev/null +++ b/1.2/assets/crowlogo_main_color.svg @@ -0,0 +1,90 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/1.2/assets/crowlogo_main_light_color.svg b/1.2/assets/crowlogo_main_light_color.svg new file mode 100644 index 000000000..85463761f --- /dev/null +++ b/1.2/assets/crowlogo_main_light_color.svg @@ -0,0 +1,90 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/1.2/assets/fast_icon.svg b/1.2/assets/fast_icon.svg new file mode 100644 index 000000000..3c87ba259 --- /dev/null +++ b/1.2/assets/fast_icon.svg @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + diff --git a/1.2/assets/fast_light_icon.svg b/1.2/assets/fast_light_icon.svg new file mode 100644 index 000000000..9b0007cfe --- /dev/null +++ b/1.2/assets/fast_light_icon.svg @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + diff --git a/1.2/assets/favicon.png b/1.2/assets/favicon.png new file mode 100644 index 000000000..81ff297d2 Binary files /dev/null and b/1.2/assets/favicon.png differ diff --git a/1.2/assets/favicon.svg b/1.2/assets/favicon.svg new file mode 100644 index 000000000..3ef8866f9 --- /dev/null +++ b/1.2/assets/favicon.svg @@ -0,0 +1,102 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/1.2/assets/header_icon.svg b/1.2/assets/header_icon.svg new file mode 100644 index 000000000..f82df10fd --- /dev/null +++ b/1.2/assets/header_icon.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + diff --git a/1.2/assets/header_light_icon.svg b/1.2/assets/header_light_icon.svg new file mode 100644 index 000000000..3088b309b --- /dev/null +++ b/1.2/assets/header_light_icon.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + diff --git a/1.2/assets/images/favicon.png b/1.2/assets/images/favicon.png new file mode 100644 index 000000000..1cf13b9f9 Binary files /dev/null and b/1.2/assets/images/favicon.png differ diff --git a/1.2/assets/javascripts/bundle.081f42fc.min.js b/1.2/assets/javascripts/bundle.081f42fc.min.js new file mode 100644 index 000000000..32734cd37 --- /dev/null +++ b/1.2/assets/javascripts/bundle.081f42fc.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Fi=Object.create;var gr=Object.defineProperty;var ji=Object.getOwnPropertyDescriptor;var Wi=Object.getOwnPropertyNames,Dt=Object.getOwnPropertySymbols,Ui=Object.getPrototypeOf,xr=Object.prototype.hasOwnProperty,no=Object.prototype.propertyIsEnumerable;var oo=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,R=(e,t)=>{for(var r in t||(t={}))xr.call(t,r)&&oo(e,r,t[r]);if(Dt)for(var r of Dt(t))no.call(t,r)&&oo(e,r,t[r]);return e};var io=(e,t)=>{var r={};for(var o in e)xr.call(e,o)&&t.indexOf(o)<0&&(r[o]=e[o]);if(e!=null&&Dt)for(var o of Dt(e))t.indexOf(o)<0&&no.call(e,o)&&(r[o]=e[o]);return r};var yr=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Di=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Wi(t))!xr.call(e,n)&&n!==r&&gr(e,n,{get:()=>t[n],enumerable:!(o=ji(t,n))||o.enumerable});return e};var Vt=(e,t,r)=>(r=e!=null?Fi(Ui(e)):{},Di(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var ao=(e,t,r)=>new Promise((o,n)=>{var i=p=>{try{s(r.next(p))}catch(c){n(c)}},a=p=>{try{s(r.throw(p))}catch(c){n(c)}},s=p=>p.done?o(p.value):Promise.resolve(p.value).then(i,a);s((r=r.apply(e,t)).next())});var co=yr((Er,so)=>{(function(e,t){typeof Er=="object"&&typeof so!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(Er,function(){"use strict";function e(r){var o=!0,n=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(H){return!!(H&&H!==document&&H.nodeName!=="HTML"&&H.nodeName!=="BODY"&&"classList"in H&&"contains"in H.classList)}function p(H){var mt=H.type,ze=H.tagName;return!!(ze==="INPUT"&&a[mt]&&!H.readOnly||ze==="TEXTAREA"&&!H.readOnly||H.isContentEditable)}function c(H){H.classList.contains("focus-visible")||(H.classList.add("focus-visible"),H.setAttribute("data-focus-visible-added",""))}function l(H){H.hasAttribute("data-focus-visible-added")&&(H.classList.remove("focus-visible"),H.removeAttribute("data-focus-visible-added"))}function f(H){H.metaKey||H.altKey||H.ctrlKey||(s(r.activeElement)&&c(r.activeElement),o=!0)}function u(H){o=!1}function h(H){s(H.target)&&(o||p(H.target))&&c(H.target)}function w(H){s(H.target)&&(H.target.classList.contains("focus-visible")||H.target.hasAttribute("data-focus-visible-added"))&&(n=!0,window.clearTimeout(i),i=window.setTimeout(function(){n=!1},100),l(H.target))}function A(H){document.visibilityState==="hidden"&&(n&&(o=!0),te())}function te(){document.addEventListener("mousemove",J),document.addEventListener("mousedown",J),document.addEventListener("mouseup",J),document.addEventListener("pointermove",J),document.addEventListener("pointerdown",J),document.addEventListener("pointerup",J),document.addEventListener("touchmove",J),document.addEventListener("touchstart",J),document.addEventListener("touchend",J)}function ie(){document.removeEventListener("mousemove",J),document.removeEventListener("mousedown",J),document.removeEventListener("mouseup",J),document.removeEventListener("pointermove",J),document.removeEventListener("pointerdown",J),document.removeEventListener("pointerup",J),document.removeEventListener("touchmove",J),document.removeEventListener("touchstart",J),document.removeEventListener("touchend",J)}function J(H){H.target.nodeName&&H.target.nodeName.toLowerCase()==="html"||(o=!1,ie())}document.addEventListener("keydown",f,!0),document.addEventListener("mousedown",u,!0),document.addEventListener("pointerdown",u,!0),document.addEventListener("touchstart",u,!0),document.addEventListener("visibilitychange",A,!0),te(),r.addEventListener("focus",h,!0),r.addEventListener("blur",w,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var Yr=yr((Rt,Kr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Rt=="object"&&typeof Kr=="object"?Kr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Rt=="object"?Rt.ClipboardJS=r():t.ClipboardJS=r()})(Rt,function(){return function(){var e={686:function(o,n,i){"use strict";i.d(n,{default:function(){return Ii}});var a=i(279),s=i.n(a),p=i(370),c=i.n(p),l=i(817),f=i.n(l);function u(V){try{return document.execCommand(V)}catch(_){return!1}}var h=function(_){var O=f()(_);return u("cut"),O},w=h;function A(V){var _=document.documentElement.getAttribute("dir")==="rtl",O=document.createElement("textarea");O.style.fontSize="12pt",O.style.border="0",O.style.padding="0",O.style.margin="0",O.style.position="absolute",O.style[_?"right":"left"]="-9999px";var j=window.pageYOffset||document.documentElement.scrollTop;return O.style.top="".concat(j,"px"),O.setAttribute("readonly",""),O.value=V,O}var te=function(_,O){var j=A(_);O.container.appendChild(j);var D=f()(j);return u("copy"),j.remove(),D},ie=function(_){var O=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},j="";return typeof _=="string"?j=te(_,O):_ instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(_==null?void 0:_.type)?j=te(_.value,O):(j=f()(_),u("copy")),j},J=ie;function H(V){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?H=function(O){return typeof O}:H=function(O){return O&&typeof Symbol=="function"&&O.constructor===Symbol&&O!==Symbol.prototype?"symbol":typeof O},H(V)}var mt=function(){var _=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},O=_.action,j=O===void 0?"copy":O,D=_.container,Y=_.target,ke=_.text;if(j!=="copy"&&j!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(Y!==void 0)if(Y&&H(Y)==="object"&&Y.nodeType===1){if(j==="copy"&&Y.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(j==="cut"&&(Y.hasAttribute("readonly")||Y.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(ke)return J(ke,{container:D});if(Y)return j==="cut"?w(Y):J(Y,{container:D})},ze=mt;function Ie(V){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ie=function(O){return typeof O}:Ie=function(O){return O&&typeof Symbol=="function"&&O.constructor===Symbol&&O!==Symbol.prototype?"symbol":typeof O},Ie(V)}function _i(V,_){if(!(V instanceof _))throw new TypeError("Cannot call a class as a function")}function ro(V,_){for(var O=0;O<_.length;O++){var j=_[O];j.enumerable=j.enumerable||!1,j.configurable=!0,"value"in j&&(j.writable=!0),Object.defineProperty(V,j.key,j)}}function Ai(V,_,O){return _&&ro(V.prototype,_),O&&ro(V,O),V}function Ci(V,_){if(typeof _!="function"&&_!==null)throw new TypeError("Super expression must either be null or a function");V.prototype=Object.create(_&&_.prototype,{constructor:{value:V,writable:!0,configurable:!0}}),_&&br(V,_)}function br(V,_){return br=Object.setPrototypeOf||function(j,D){return j.__proto__=D,j},br(V,_)}function Hi(V){var _=Pi();return function(){var j=Wt(V),D;if(_){var Y=Wt(this).constructor;D=Reflect.construct(j,arguments,Y)}else D=j.apply(this,arguments);return ki(this,D)}}function ki(V,_){return _&&(Ie(_)==="object"||typeof _=="function")?_:$i(V)}function $i(V){if(V===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return V}function Pi(){if(typeof Reflect=="undefined"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(V){return!1}}function Wt(V){return Wt=Object.setPrototypeOf?Object.getPrototypeOf:function(O){return O.__proto__||Object.getPrototypeOf(O)},Wt(V)}function vr(V,_){var O="data-clipboard-".concat(V);if(_.hasAttribute(O))return _.getAttribute(O)}var Ri=function(V){Ci(O,V);var _=Hi(O);function O(j,D){var Y;return _i(this,O),Y=_.call(this),Y.resolveOptions(D),Y.listenClick(j),Y}return Ai(O,[{key:"resolveOptions",value:function(){var D=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof D.action=="function"?D.action:this.defaultAction,this.target=typeof D.target=="function"?D.target:this.defaultTarget,this.text=typeof D.text=="function"?D.text:this.defaultText,this.container=Ie(D.container)==="object"?D.container:document.body}},{key:"listenClick",value:function(D){var Y=this;this.listener=c()(D,"click",function(ke){return Y.onClick(ke)})}},{key:"onClick",value:function(D){var Y=D.delegateTarget||D.currentTarget,ke=this.action(Y)||"copy",Ut=ze({action:ke,container:this.container,target:this.target(Y),text:this.text(Y)});this.emit(Ut?"success":"error",{action:ke,text:Ut,trigger:Y,clearSelection:function(){Y&&Y.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(D){return vr("action",D)}},{key:"defaultTarget",value:function(D){var Y=vr("target",D);if(Y)return document.querySelector(Y)}},{key:"defaultText",value:function(D){return vr("text",D)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(D){var Y=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return J(D,Y)}},{key:"cut",value:function(D){return w(D)}},{key:"isSupported",value:function(){var D=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],Y=typeof D=="string"?[D]:D,ke=!!document.queryCommandSupported;return Y.forEach(function(Ut){ke=ke&&!!document.queryCommandSupported(Ut)}),ke}}]),O}(s()),Ii=Ri},828:function(o){var n=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,p){for(;s&&s.nodeType!==n;){if(typeof s.matches=="function"&&s.matches(p))return s;s=s.parentNode}}o.exports=a},438:function(o,n,i){var a=i(828);function s(l,f,u,h,w){var A=c.apply(this,arguments);return l.addEventListener(u,A,w),{destroy:function(){l.removeEventListener(u,A,w)}}}function p(l,f,u,h,w){return typeof l.addEventListener=="function"?s.apply(null,arguments):typeof u=="function"?s.bind(null,document).apply(null,arguments):(typeof l=="string"&&(l=document.querySelectorAll(l)),Array.prototype.map.call(l,function(A){return s(A,f,u,h,w)}))}function c(l,f,u,h){return function(w){w.delegateTarget=a(w.target,f),w.delegateTarget&&h.call(l,w)}}o.exports=p},879:function(o,n){n.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},n.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||n.node(i[0]))},n.string=function(i){return typeof i=="string"||i instanceof String},n.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(o,n,i){var a=i(879),s=i(438);function p(u,h,w){if(!u&&!h&&!w)throw new Error("Missing required arguments");if(!a.string(h))throw new TypeError("Second argument must be a String");if(!a.fn(w))throw new TypeError("Third argument must be a Function");if(a.node(u))return c(u,h,w);if(a.nodeList(u))return l(u,h,w);if(a.string(u))return f(u,h,w);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(u,h,w){return u.addEventListener(h,w),{destroy:function(){u.removeEventListener(h,w)}}}function l(u,h,w){return Array.prototype.forEach.call(u,function(A){A.addEventListener(h,w)}),{destroy:function(){Array.prototype.forEach.call(u,function(A){A.removeEventListener(h,w)})}}}function f(u,h,w){return s(document.body,u,h,w)}o.exports=p},817:function(o){function n(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var p=window.getSelection(),c=document.createRange();c.selectNodeContents(i),p.removeAllRanges(),p.addRange(c),a=p.toString()}return a}o.exports=n},279:function(o){function n(){}n.prototype={on:function(i,a,s){var p=this.e||(this.e={});return(p[i]||(p[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var p=this;function c(){p.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),p=0,c=s.length;for(p;p{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var ts=/["'&<>]/;ei.exports=rs;function rs(e){var t=""+e,r=ts.exec(t);if(!r)return t;var o,n="",i=0,a=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function N(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var o=r.call(e),n,i=[],a;try{for(;(t===void 0||t-- >0)&&!(n=o.next()).done;)i.push(n.value)}catch(s){a={error:s}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(a)throw a.error}}return i}function q(e,t,r){if(r||arguments.length===2)for(var o=0,n=t.length,i;o1||s(u,h)})})}function s(u,h){try{p(o[u](h))}catch(w){f(i[0][3],w)}}function p(u){u.value instanceof nt?Promise.resolve(u.value.v).then(c,l):f(i[0][2],u)}function c(u){s("next",u)}function l(u){s("throw",u)}function f(u,h){u(h),i.shift(),i.length&&s(i[0][0],i[0][1])}}function mo(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof de=="function"?de(e):e[Symbol.iterator](),r={},o("next"),o("throw"),o("return"),r[Symbol.asyncIterator]=function(){return this},r);function o(i){r[i]=e[i]&&function(a){return new Promise(function(s,p){a=e[i](a),n(s,p,a.done,a.value)})}}function n(i,a,s,p){Promise.resolve(p).then(function(c){i({value:c,done:s})},a)}}function k(e){return typeof e=="function"}function ft(e){var t=function(o){Error.call(o),o.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var zt=ft(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(o,n){return n+1+") "+o.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function qe(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Fe=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,o,n,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=de(a),p=s.next();!p.done;p=s.next()){var c=p.value;c.remove(this)}}catch(A){t={error:A}}finally{try{p&&!p.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var l=this.initialTeardown;if(k(l))try{l()}catch(A){i=A instanceof zt?A.errors:[A]}var f=this._finalizers;if(f){this._finalizers=null;try{for(var u=de(f),h=u.next();!h.done;h=u.next()){var w=h.value;try{fo(w)}catch(A){i=i!=null?i:[],A instanceof zt?i=q(q([],N(i)),N(A.errors)):i.push(A)}}}catch(A){o={error:A}}finally{try{h&&!h.done&&(n=u.return)&&n.call(u)}finally{if(o)throw o.error}}}if(i)throw new zt(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)fo(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&qe(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&qe(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Tr=Fe.EMPTY;function qt(e){return e instanceof Fe||e&&"closed"in e&&k(e.remove)&&k(e.add)&&k(e.unsubscribe)}function fo(e){k(e)?e():e.unsubscribe()}var $e={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var ut={setTimeout:function(e,t){for(var r=[],o=2;o0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var o=this,n=this,i=n.hasError,a=n.isStopped,s=n.observers;return i||a?Tr:(this.currentObservers=null,s.push(r),new Fe(function(){o.currentObservers=null,qe(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var o=this,n=o.hasError,i=o.thrownError,a=o.isStopped;n?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new F;return r.source=this,r},t.create=function(r,o){return new Eo(r,o)},t}(F);var Eo=function(e){re(t,e);function t(r,o){var n=e.call(this)||this;return n.destination=r,n.source=o,n}return t.prototype.next=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.next)===null||n===void 0||n.call(o,r)},t.prototype.error=function(r){var o,n;(n=(o=this.destination)===null||o===void 0?void 0:o.error)===null||n===void 0||n.call(o,r)},t.prototype.complete=function(){var r,o;(o=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||o===void 0||o.call(r)},t.prototype._subscribe=function(r){var o,n;return(n=(o=this.source)===null||o===void 0?void 0:o.subscribe(r))!==null&&n!==void 0?n:Tr},t}(g);var _r=function(e){re(t,e);function t(r){var o=e.call(this)||this;return o._value=r,o}return Object.defineProperty(t.prototype,"value",{get:function(){return this.getValue()},enumerable:!1,configurable:!0}),t.prototype._subscribe=function(r){var o=e.prototype._subscribe.call(this,r);return!o.closed&&r.next(this._value),o},t.prototype.getValue=function(){var r=this,o=r.hasError,n=r.thrownError,i=r._value;if(o)throw n;return this._throwIfClosed(),i},t.prototype.next=function(r){e.prototype.next.call(this,this._value=r)},t}(g);var Lt={now:function(){return(Lt.delegate||Date).now()},delegate:void 0};var _t=function(e){re(t,e);function t(r,o,n){r===void 0&&(r=1/0),o===void 0&&(o=1/0),n===void 0&&(n=Lt);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=o,i._timestampProvider=n,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=o===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,o),i}return t.prototype.next=function(r){var o=this,n=o.isStopped,i=o._buffer,a=o._infiniteTimeWindow,s=o._timestampProvider,p=o._windowTime;n||(i.push(r),!a&&i.push(s.now()+p)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var o=this._innerSubscribe(r),n=this,i=n._infiniteTimeWindow,a=n._buffer,s=a.slice(),p=0;p0?e.prototype.schedule.call(this,r,o):(this.delay=o,this.state=r,this.scheduler.flush(this),this)},t.prototype.execute=function(r,o){return o>0||this.closed?e.prototype.execute.call(this,r,o):this._execute(r,o)},t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!=null&&n>0||n==null&&this.delay>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.flush(this),0)},t}(vt);var So=function(e){re(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t}(gt);var Hr=new So(To);var Oo=function(e){re(t,e);function t(r,o){var n=e.call(this,r,o)||this;return n.scheduler=r,n.work=o,n}return t.prototype.requestAsyncId=function(r,o,n){return n===void 0&&(n=0),n!==null&&n>0?e.prototype.requestAsyncId.call(this,r,o,n):(r.actions.push(this),r._scheduled||(r._scheduled=bt.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,o,n){var i;if(n===void 0&&(n=0),n!=null?n>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,o,n);var a=r.actions;o!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==o&&(bt.cancelAnimationFrame(o),r._scheduled=void 0)},t}(vt);var Mo=function(e){re(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var o=this._scheduled;this._scheduled=void 0;var n=this.actions,i;r=r||n.shift();do if(i=r.execute(r.state,r.delay))break;while((r=n[0])&&r.id===o&&n.shift());if(this._active=!1,i){for(;(r=n[0])&&r.id===o&&n.shift();)r.unsubscribe();throw i}},t}(gt);var me=new Mo(Oo);var M=new F(function(e){return e.complete()});function Yt(e){return e&&k(e.schedule)}function kr(e){return e[e.length-1]}function Xe(e){return k(kr(e))?e.pop():void 0}function He(e){return Yt(kr(e))?e.pop():void 0}function Bt(e,t){return typeof kr(e)=="number"?e.pop():t}var xt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Gt(e){return k(e==null?void 0:e.then)}function Jt(e){return k(e[ht])}function Xt(e){return Symbol.asyncIterator&&k(e==null?void 0:e[Symbol.asyncIterator])}function Zt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Gi(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var er=Gi();function tr(e){return k(e==null?void 0:e[er])}function rr(e){return lo(this,arguments,function(){var r,o,n,i;return Nt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,nt(r.read())];case 3:return o=a.sent(),n=o.value,i=o.done,i?[4,nt(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,nt(n)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function or(e){return k(e==null?void 0:e.getReader)}function W(e){if(e instanceof F)return e;if(e!=null){if(Jt(e))return Ji(e);if(xt(e))return Xi(e);if(Gt(e))return Zi(e);if(Xt(e))return Lo(e);if(tr(e))return ea(e);if(or(e))return ta(e)}throw Zt(e)}function Ji(e){return new F(function(t){var r=e[ht]();if(k(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Xi(e){return new F(function(t){for(var r=0;r=2;return function(o){return o.pipe(e?v(function(n,i){return e(n,i,o)}):le,Te(1),r?Be(t):zo(function(){return new ir}))}}function Fr(e){return e<=0?function(){return M}:y(function(t,r){var o=[];t.subscribe(T(r,function(n){o.push(n),e=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new g}:t,o=e.resetOnError,n=o===void 0?!0:o,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,p=s===void 0?!0:s;return function(c){var l,f,u,h=0,w=!1,A=!1,te=function(){f==null||f.unsubscribe(),f=void 0},ie=function(){te(),l=u=void 0,w=A=!1},J=function(){var H=l;ie(),H==null||H.unsubscribe()};return y(function(H,mt){h++,!A&&!w&&te();var ze=u=u!=null?u:r();mt.add(function(){h--,h===0&&!A&&!w&&(f=Wr(J,p))}),ze.subscribe(mt),!l&&h>0&&(l=new at({next:function(Ie){return ze.next(Ie)},error:function(Ie){A=!0,te(),f=Wr(ie,n,Ie),ze.error(Ie)},complete:function(){w=!0,te(),f=Wr(ie,a),ze.complete()}}),W(H).subscribe(l))})(c)}}function Wr(e,t){for(var r=[],o=2;oe.next(document)),e}function $(e,t=document){return Array.from(t.querySelectorAll(e))}function P(e,t=document){let r=fe(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function fe(e,t=document){return t.querySelector(e)||void 0}function Re(){var e,t,r,o;return(o=(r=(t=(e=document.activeElement)==null?void 0:e.shadowRoot)==null?void 0:t.activeElement)!=null?r:document.activeElement)!=null?o:void 0}var xa=S(d(document.body,"focusin"),d(document.body,"focusout")).pipe(_e(1),Q(void 0),m(()=>Re()||document.body),B(1));function et(e){return xa.pipe(m(t=>e.contains(t)),K())}function kt(e,t){return C(()=>S(d(e,"mouseenter").pipe(m(()=>!0)),d(e,"mouseleave").pipe(m(()=>!1))).pipe(t?Ht(r=>Me(+!r*t)):le,Q(e.matches(":hover"))))}function Bo(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)Bo(e,r)}function x(e,t,...r){let o=document.createElement(e);if(t)for(let n of Object.keys(t))typeof t[n]!="undefined"&&(typeof t[n]!="boolean"?o.setAttribute(n,t[n]):o.setAttribute(n,""));for(let n of r)Bo(o,n);return o}function sr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function wt(e){let t=x("script",{src:e});return C(()=>(document.head.appendChild(t),S(d(t,"load"),d(t,"error").pipe(b(()=>$r(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(m(()=>{}),L(()=>document.head.removeChild(t)),Te(1))))}var Go=new g,ya=C(()=>typeof ResizeObserver=="undefined"?wt("https://unpkg.com/resize-observer-polyfill"):I(void 0)).pipe(m(()=>new ResizeObserver(e=>e.forEach(t=>Go.next(t)))),b(e=>S(Ke,I(e)).pipe(L(()=>e.disconnect()))),B(1));function ce(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){let t=e;for(;t.clientWidth===0&&t.parentElement;)t=t.parentElement;return ya.pipe(E(r=>r.observe(t)),b(r=>Go.pipe(v(o=>o.target===t),L(()=>r.unobserve(t)))),m(()=>ce(e)),Q(ce(e)))}function Tt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function cr(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}function Jo(e){let t=[],r=e.parentElement;for(;r;)(e.clientWidth>r.clientWidth||e.clientHeight>r.clientHeight)&&t.push(r),r=(e=r).parentElement;return t.length===0&&t.push(document.documentElement),t}function Ue(e){return{x:e.offsetLeft,y:e.offsetTop}}function Xo(e){let t=e.getBoundingClientRect();return{x:t.x+window.scrollX,y:t.y+window.scrollY}}function Zo(e){return S(d(window,"load"),d(window,"resize")).pipe(Le(0,me),m(()=>Ue(e)),Q(Ue(e)))}function pr(e){return{x:e.scrollLeft,y:e.scrollTop}}function De(e){return S(d(e,"scroll"),d(window,"scroll"),d(window,"resize")).pipe(Le(0,me),m(()=>pr(e)),Q(pr(e)))}var en=new g,Ea=C(()=>I(new IntersectionObserver(e=>{for(let t of e)en.next(t)},{threshold:0}))).pipe(b(e=>S(Ke,I(e)).pipe(L(()=>e.disconnect()))),B(1));function tt(e){return Ea.pipe(E(t=>t.observe(e)),b(t=>en.pipe(v(({target:r})=>r===e),L(()=>t.unobserve(e)),m(({isIntersecting:r})=>r))))}function tn(e,t=16){return De(e).pipe(m(({y:r})=>{let o=ce(e),n=Tt(e);return r>=n.height-o.height-t}),K())}var lr={drawer:P("[data-md-toggle=drawer]"),search:P("[data-md-toggle=search]")};function rn(e){return lr[e].checked}function Je(e,t){lr[e].checked!==t&&lr[e].click()}function Ve(e){let t=lr[e];return d(t,"change").pipe(m(()=>t.checked),Q(t.checked))}function wa(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ta(){return S(d(window,"compositionstart").pipe(m(()=>!0)),d(window,"compositionend").pipe(m(()=>!1))).pipe(Q(!1))}function on(){let e=d(window,"keydown").pipe(v(t=>!(t.metaKey||t.ctrlKey)),m(t=>({mode:rn("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),v(({mode:t,type:r})=>{if(t==="global"){let o=Re();if(typeof o!="undefined")return!wa(o,r)}return!0}),pe());return Ta().pipe(b(t=>t?M:e))}function xe(){return new URL(location.href)}function pt(e,t=!1){if(G("navigation.instant")&&!t){let r=x("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function nn(){return new g}function an(){return location.hash.slice(1)}function sn(e){let t=x("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Sa(e){return S(d(window,"hashchange"),e).pipe(m(an),Q(an()),v(t=>t.length>0),B(1))}function cn(e){return Sa(e).pipe(m(t=>fe(`[id="${t}"]`)),v(t=>typeof t!="undefined"))}function $t(e){let t=matchMedia(e);return ar(r=>t.addListener(()=>r(t.matches))).pipe(Q(t.matches))}function pn(){let e=matchMedia("print");return S(d(window,"beforeprint").pipe(m(()=>!0)),d(window,"afterprint").pipe(m(()=>!1))).pipe(Q(e.matches))}function Nr(e,t){return e.pipe(b(r=>r?t():M))}function zr(e,t){return new F(r=>{let o=new XMLHttpRequest;return o.open("GET",`${e}`),o.responseType="blob",o.addEventListener("load",()=>{o.status>=200&&o.status<300?(r.next(o.response),r.complete()):r.error(new Error(o.statusText))}),o.addEventListener("error",()=>{r.error(new Error("Network error"))}),o.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(o.addEventListener("progress",n=>{var i;if(n.lengthComputable)t.progress$.next(n.loaded/n.total*100);else{let a=(i=o.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(n.loaded/+a*100)}}),t.progress$.next(5)),o.send(),()=>o.abort()})}function Ne(e,t){return zr(e,t).pipe(b(r=>r.text()),m(r=>JSON.parse(r)),B(1))}function ln(e,t){let r=new DOMParser;return zr(e,t).pipe(b(o=>o.text()),m(o=>r.parseFromString(o,"text/html")),B(1))}function mn(e,t){let r=new DOMParser;return zr(e,t).pipe(b(o=>o.text()),m(o=>r.parseFromString(o,"text/xml")),B(1))}function fn(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function un(){return S(d(window,"scroll",{passive:!0}),d(window,"resize",{passive:!0})).pipe(m(fn),Q(fn()))}function dn(){return{width:innerWidth,height:innerHeight}}function hn(){return d(window,"resize",{passive:!0}).pipe(m(dn),Q(dn()))}function bn(){return z([un(),hn()]).pipe(m(([e,t])=>({offset:e,size:t})),B(1))}function mr(e,{viewport$:t,header$:r}){let o=t.pipe(Z("size")),n=z([o,r]).pipe(m(()=>Ue(e)));return z([r,t,n]).pipe(m(([{height:i},{offset:a,size:s},{x:p,y:c}])=>({offset:{x:a.x-p,y:a.y-c+i},size:s})))}function Oa(e){return d(e,"message",t=>t.data)}function Ma(e){let t=new g;return t.subscribe(r=>e.postMessage(r)),t}function vn(e,t=new Worker(e)){let r=Oa(t),o=Ma(t),n=new g;n.subscribe(o);let i=o.pipe(X(),ne(!0));return n.pipe(X(),Pe(r.pipe(U(i))),pe())}var La=P("#__config"),St=JSON.parse(La.textContent);St.base=`${new URL(St.base,xe())}`;function ye(){return St}function G(e){return St.features.includes(e)}function Ee(e,t){return typeof t!="undefined"?St.translations[e].replace("#",t.toString()):St.translations[e]}function Se(e,t=document){return P(`[data-md-component=${e}]`,t)}function ae(e,t=document){return $(`[data-md-component=${e}]`,t)}function _a(e){let t=P(".md-typeset > :first-child",e);return d(t,"click",{once:!0}).pipe(m(()=>P(".md-typeset",e)),m(r=>({hash:__md_hash(r.innerHTML)})))}function gn(e){if(!G("announce.dismiss")||!e.childElementCount)return M;if(!e.hidden){let t=P(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return C(()=>{let t=new g;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),_a(e).pipe(E(r=>t.next(r)),L(()=>t.complete()),m(r=>R({ref:e},r)))})}function Aa(e,{target$:t}){return t.pipe(m(r=>({hidden:r!==e})))}function xn(e,t){let r=new g;return r.subscribe(({hidden:o})=>{e.hidden=o}),Aa(e,t).pipe(E(o=>r.next(o)),L(()=>r.complete()),m(o=>R({ref:e},o)))}function Pt(e,t){return t==="inline"?x("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"})):x("div",{class:"md-tooltip",id:e,role:"tooltip"},x("div",{class:"md-tooltip__inner md-typeset"}))}function yn(...e){return x("div",{class:"md-tooltip2",role:"tooltip"},x("div",{class:"md-tooltip2__inner md-typeset"},e))}function En(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return x("aside",{class:"md-annotation",tabIndex:0},Pt(t),x("a",{href:r,class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}else return x("aside",{class:"md-annotation",tabIndex:0},Pt(t),x("span",{class:"md-annotation__index",tabIndex:-1},x("span",{"data-md-annotation-id":e})))}function wn(e){return x("button",{class:"md-clipboard md-icon",title:Ee("clipboard.copy"),"data-clipboard-target":`#${e} > code`})}function qr(e,t){let r=t&2,o=t&1,n=Object.keys(e.terms).filter(p=>!e.terms[p]).reduce((p,c)=>[...p,x("del",null,c)," "],[]).slice(0,-1),i=ye(),a=new URL(e.location,i.base);G("search.highlight")&&a.searchParams.set("h",Object.entries(e.terms).filter(([,p])=>p).reduce((p,[c])=>`${p} ${c}`.trim(),""));let{tags:s}=ye();return x("a",{href:`${a}`,class:"md-search-result__link",tabIndex:-1},x("article",{class:"md-search-result__article md-typeset","data-md-score":e.score.toFixed(2)},r>0&&x("div",{class:"md-search-result__icon md-icon"}),r>0&&x("h1",null,e.title),r<=0&&x("h2",null,e.title),o>0&&e.text.length>0&&e.text,e.tags&&e.tags.map(p=>{let c=s?p in s?`md-tag-icon md-tag--${s[p]}`:"md-tag-icon":"";return x("span",{class:`md-tag ${c}`},p)}),o>0&&n.length>0&&x("p",{class:"md-search-result__terms"},Ee("search.result.term.missing"),": ",...n)))}function Tn(e){let t=e[0].score,r=[...e],o=ye(),n=r.findIndex(l=>!`${new URL(l.location,o.base)}`.includes("#")),[i]=r.splice(n,1),a=r.findIndex(l=>l.scoreqr(l,1)),...p.length?[x("details",{class:"md-search-result__more"},x("summary",{tabIndex:-1},x("div",null,p.length>0&&p.length===1?Ee("search.result.more.one"):Ee("search.result.more.other",p.length))),...p.map(l=>qr(l,1)))]:[]];return x("li",{class:"md-search-result__item"},c)}function Sn(e){return x("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>x("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?sr(r):r)))}function Qr(e){let t=`tabbed-control tabbed-control--${e}`;return x("div",{class:t,hidden:!0},x("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function On(e){return x("div",{class:"md-typeset__scrollwrap"},x("div",{class:"md-typeset__table"},e))}function Ca(e){var o;let t=ye(),r=new URL(`../${e.version}/`,t.base);return x("li",{class:"md-version__item"},x("a",{href:`${r}`,class:"md-version__link"},e.title,((o=t.version)==null?void 0:o.alias)&&e.aliases.length>0&&x("span",{class:"md-version__alias"},e.aliases[0])))}function Mn(e,t){var o;let r=ye();return e=e.filter(n=>{var i;return!((i=n.properties)!=null&&i.hidden)}),x("div",{class:"md-version"},x("button",{class:"md-version__current","aria-label":Ee("select.version")},t.title,((o=r.version)==null?void 0:o.alias)&&t.aliases.length>0&&x("span",{class:"md-version__alias"},t.aliases[0])),x("ul",{class:"md-version__list"},e.map(Ca)))}var Ha=0;function ka(e){let t=z([et(e),kt(e)]).pipe(m(([o,n])=>o||n),K()),r=C(()=>Jo(e)).pipe(oe(De),ct(1),m(()=>Xo(e)));return t.pipe(Ae(o=>o),b(()=>z([t,r])),m(([o,n])=>({active:o,offset:n})),pe())}function $a(e,t){let{content$:r,viewport$:o}=t,n=`__tooltip2_${Ha++}`;return C(()=>{let i=new g,a=new _r(!1);i.pipe(X(),ne(!1)).subscribe(a);let s=a.pipe(Ht(c=>Me(+!c*250,Hr)),K(),b(c=>c?r:M),E(c=>c.id=n),pe());z([i.pipe(m(({active:c})=>c)),s.pipe(b(c=>kt(c,250)),Q(!1))]).pipe(m(c=>c.some(l=>l))).subscribe(a);let p=a.pipe(v(c=>c),ee(s,o),m(([c,l,{size:f}])=>{let u=e.getBoundingClientRect(),h=u.width/2;if(l.role==="tooltip")return{x:h,y:8+u.height};if(u.y>=f.height/2){let{height:w}=ce(l);return{x:h,y:-16-w}}else return{x:h,y:16+u.height}}));return z([s,i,p]).subscribe(([c,{offset:l},f])=>{c.style.setProperty("--md-tooltip-host-x",`${l.x}px`),c.style.setProperty("--md-tooltip-host-y",`${l.y}px`),c.style.setProperty("--md-tooltip-x",`${f.x}px`),c.style.setProperty("--md-tooltip-y",`${f.y}px`),c.classList.toggle("md-tooltip2--top",f.y<0),c.classList.toggle("md-tooltip2--bottom",f.y>=0)}),a.pipe(v(c=>c),ee(s,(c,l)=>l),v(c=>c.role==="tooltip")).subscribe(c=>{let l=ce(P(":scope > *",c));c.style.setProperty("--md-tooltip-width",`${l.width}px`),c.style.setProperty("--md-tooltip-tail","0px")}),a.pipe(K(),be(me),ee(s)).subscribe(([c,l])=>{l.classList.toggle("md-tooltip2--active",c)}),z([a.pipe(v(c=>c)),s]).subscribe(([c,l])=>{l.role==="dialog"?(e.setAttribute("aria-controls",n),e.setAttribute("aria-haspopup","dialog")):e.setAttribute("aria-describedby",n)}),a.pipe(v(c=>!c)).subscribe(()=>{e.removeAttribute("aria-controls"),e.removeAttribute("aria-describedby"),e.removeAttribute("aria-haspopup")}),ka(e).pipe(E(c=>i.next(c)),L(()=>i.complete()),m(c=>R({ref:e},c)))})}function lt(e,{viewport$:t},r=document.body){return $a(e,{content$:new F(o=>{let n=e.title,i=yn(n);return o.next(i),e.removeAttribute("title"),r.append(i),()=>{i.remove(),e.setAttribute("title",n)}}),viewport$:t})}function Pa(e,t){let r=C(()=>z([Zo(e),De(t)])).pipe(m(([{x:o,y:n},i])=>{let{width:a,height:s}=ce(e);return{x:o-i.x+a/2,y:n-i.y+s/2}}));return et(e).pipe(b(o=>r.pipe(m(n=>({active:o,offset:n})),Te(+!o||1/0))))}function Ln(e,t,{target$:r}){let[o,n]=Array.from(e.children);return C(()=>{let i=new g,a=i.pipe(X(),ne(!0));return i.subscribe({next({offset:s}){e.style.setProperty("--md-tooltip-x",`${s.x}px`),e.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),tt(e).pipe(U(a)).subscribe(s=>{e.toggleAttribute("data-md-visible",s)}),S(i.pipe(v(({active:s})=>s)),i.pipe(_e(250),v(({active:s})=>!s))).subscribe({next({active:s}){s?e.prepend(o):o.remove()},complete(){e.prepend(o)}}),i.pipe(Le(16,me)).subscribe(({active:s})=>{o.classList.toggle("md-tooltip--active",s)}),i.pipe(ct(125,me),v(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:s})=>s)).subscribe({next(s){s?e.style.setProperty("--md-tooltip-0",`${-s}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),d(n,"click").pipe(U(a),v(s=>!(s.metaKey||s.ctrlKey))).subscribe(s=>{s.stopPropagation(),s.preventDefault()}),d(n,"mousedown").pipe(U(a),ee(i)).subscribe(([s,{active:p}])=>{var c;if(s.button!==0||s.metaKey||s.ctrlKey)s.preventDefault();else if(p){s.preventDefault();let l=e.parentElement.closest(".md-annotation");l instanceof HTMLElement?l.focus():(c=Re())==null||c.blur()}}),r.pipe(U(a),v(s=>s===o),Ge(125)).subscribe(()=>e.focus()),Pa(e,t).pipe(E(s=>i.next(s)),L(()=>i.complete()),m(s=>R({ref:e},s)))})}function Ra(e){return e.tagName==="CODE"?$(".c, .c1, .cm",e):[e]}function Ia(e){let t=[];for(let r of Ra(e)){let o=[],n=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=n.nextNode();i;i=n.nextNode())o.push(i);for(let i of o){let a;for(;a=/(\(\d+\))(!)?/.exec(i.textContent);){let[,s,p]=a;if(typeof p=="undefined"){let c=i.splitText(a.index);i=c.splitText(s.length),t.push(c)}else{i.textContent=s,t.push(i);break}}}}return t}function _n(e,t){t.append(...Array.from(e.childNodes))}function fr(e,t,{target$:r,print$:o}){let n=t.closest("[id]"),i=n==null?void 0:n.id,a=new Map;for(let s of Ia(t)){let[,p]=s.textContent.match(/\((\d+)\)/);fe(`:scope > li:nth-child(${p})`,e)&&(a.set(p,En(p,i)),s.replaceWith(a.get(p)))}return a.size===0?M:C(()=>{let s=new g,p=s.pipe(X(),ne(!0)),c=[];for(let[l,f]of a)c.push([P(".md-typeset",f),P(`:scope > li:nth-child(${l})`,e)]);return o.pipe(U(p)).subscribe(l=>{e.hidden=!l,e.classList.toggle("md-annotation-list",l);for(let[f,u]of c)l?_n(f,u):_n(u,f)}),S(...[...a].map(([,l])=>Ln(l,t,{target$:r}))).pipe(L(()=>s.complete()),pe())})}function An(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return An(t)}}function Cn(e,t){return C(()=>{let r=An(e);return typeof r!="undefined"?fr(r,e,t):M})}var Hn=Vt(Yr());var Fa=0;function kn(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return kn(t)}}function ja(e){return ge(e).pipe(m(({width:t})=>({scrollable:Tt(e).width>t})),Z("scrollable"))}function $n(e,t){let{matches:r}=matchMedia("(hover)"),o=C(()=>{let n=new g,i=n.pipe(Fr(1));n.subscribe(({scrollable:c})=>{c&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let a=[];if(Hn.default.isSupported()&&(e.closest(".copy")||G("content.code.copy")&&!e.closest(".no-copy"))){let c=e.closest("pre");c.id=`__code_${Fa++}`;let l=wn(c.id);c.insertBefore(l,e),G("content.tooltips")&&a.push(lt(l,{viewport$}))}let s=e.closest(".highlight");if(s instanceof HTMLElement){let c=kn(s);if(typeof c!="undefined"&&(s.classList.contains("annotate")||G("content.code.annotate"))){let l=fr(c,e,t);a.push(ge(s).pipe(U(i),m(({width:f,height:u})=>f&&u),K(),b(f=>f?l:M)))}}return $(":scope > span[id]",e).length&&e.classList.add("md-code__content"),ja(e).pipe(E(c=>n.next(c)),L(()=>n.complete()),m(c=>R({ref:e},c)),Pe(...a))});return G("content.lazy")?tt(e).pipe(v(n=>n),Te(1),b(()=>o)):o}function Wa(e,{target$:t,print$:r}){let o=!0;return S(t.pipe(m(n=>n.closest("details:not([open])")),v(n=>e===n),m(()=>({action:"open",reveal:!0}))),r.pipe(v(n=>n||!o),E(()=>o=e.open),m(n=>({action:n?"open":"close"}))))}function Pn(e,t){return C(()=>{let r=new g;return r.subscribe(({action:o,reveal:n})=>{e.toggleAttribute("open",o==="open"),n&&e.scrollIntoView()}),Wa(e,t).pipe(E(o=>r.next(o)),L(()=>r.complete()),m(o=>R({ref:e},o)))})}var Rn=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel rect,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel rect{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color);stroke-width:.05rem}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs #classDiagram-compositionEnd,defs #classDiagram-compositionStart,defs #classDiagram-dependencyEnd,defs #classDiagram-dependencyStart,defs #classDiagram-extensionEnd,defs #classDiagram-extensionStart{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs #classDiagram-aggregationEnd,defs #classDiagram-aggregationStart{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}a .nodeLabel{text-decoration:underline}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}.attributeBoxEven,.attributeBoxOdd{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityBox{fill:var(--md-mermaid-label-bg-color);stroke:var(--md-mermaid-node-fg-color)}.entityLabel{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.relationshipLabelBox{fill:var(--md-mermaid-label-bg-color);fill-opacity:1;background-color:var(--md-mermaid-label-bg-color);opacity:1}.relationshipLabel{fill:var(--md-mermaid-label-fg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs #ONE_OR_MORE_END *,defs #ONE_OR_MORE_START *,defs #ONLY_ONE_END *,defs #ONLY_ONE_START *,defs #ZERO_OR_MORE_END *,defs #ZERO_OR_MORE_START *,defs #ZERO_OR_ONE_END *,defs #ZERO_OR_ONE_START *{stroke:var(--md-mermaid-edge-color)!important}defs #ZERO_OR_MORE_END circle,defs #ZERO_OR_MORE_START circle{fill:var(--md-mermaid-label-bg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var Br,Da=0;function Va(){return typeof mermaid=="undefined"||mermaid instanceof Element?wt("https://unpkg.com/mermaid@10/dist/mermaid.min.js"):I(void 0)}function In(e){return e.classList.remove("mermaid"),Br||(Br=Va().pipe(E(()=>mermaid.initialize({startOnLoad:!1,themeCSS:Rn,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),m(()=>{}),B(1))),Br.subscribe(()=>ao(this,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${Da++}`,r=x("div",{class:"mermaid"}),o=e.textContent,{svg:n,fn:i}=yield mermaid.render(t,o),a=r.attachShadow({mode:"closed"});a.innerHTML=n,e.replaceWith(r),i==null||i(a)})),Br.pipe(m(()=>({ref:e})))}var Fn=x("table");function jn(e){return e.replaceWith(Fn),Fn.replaceWith(On(e)),I({ref:e})}function Na(e){let t=e.find(r=>r.checked)||e[0];return S(...e.map(r=>d(r,"change").pipe(m(()=>P(`label[for="${r.id}"]`))))).pipe(Q(P(`label[for="${t.id}"]`)),m(r=>({active:r})))}function Wn(e,{viewport$:t,target$:r}){let o=P(".tabbed-labels",e),n=$(":scope > input",e),i=Qr("prev");e.append(i);let a=Qr("next");return e.append(a),C(()=>{let s=new g,p=s.pipe(X(),ne(!0));z([s,ge(e)]).pipe(U(p),Le(1,me)).subscribe({next([{active:c},l]){let f=Ue(c),{width:u}=ce(c);e.style.setProperty("--md-indicator-x",`${f.x}px`),e.style.setProperty("--md-indicator-width",`${u}px`);let h=pr(o);(f.xh.x+l.width)&&o.scrollTo({left:Math.max(0,f.x-16),behavior:"smooth"})},complete(){e.style.removeProperty("--md-indicator-x"),e.style.removeProperty("--md-indicator-width")}}),z([De(o),ge(o)]).pipe(U(p)).subscribe(([c,l])=>{let f=Tt(o);i.hidden=c.x<16,a.hidden=c.x>f.width-l.width-16}),S(d(i,"click").pipe(m(()=>-1)),d(a,"click").pipe(m(()=>1))).pipe(U(p)).subscribe(c=>{let{width:l}=ce(o);o.scrollBy({left:l*c,behavior:"smooth"})}),r.pipe(U(p),v(c=>n.includes(c))).subscribe(c=>c.click()),o.classList.add("tabbed-labels--linked");for(let c of n){let l=P(`label[for="${c.id}"]`);l.replaceChildren(x("a",{href:`#${l.htmlFor}`,tabIndex:-1},...Array.from(l.childNodes))),d(l.firstElementChild,"click").pipe(U(p),v(f=>!(f.metaKey||f.ctrlKey)),E(f=>{f.preventDefault(),f.stopPropagation()})).subscribe(()=>{history.replaceState({},"",`#${l.htmlFor}`),l.click()})}return G("content.tabs.link")&&s.pipe(Ce(1),ee(t)).subscribe(([{active:c},{offset:l}])=>{let f=c.innerText.trim();if(c.hasAttribute("data-md-switching"))c.removeAttribute("data-md-switching");else{let u=e.offsetTop-l.y;for(let w of $("[data-tabs]"))for(let A of $(":scope > input",w)){let te=P(`label[for="${A.id}"]`);if(te!==c&&te.innerText.trim()===f){te.setAttribute("data-md-switching",""),A.click();break}}window.scrollTo({top:e.offsetTop-u});let h=__md_get("__tabs")||[];__md_set("__tabs",[...new Set([f,...h])])}}),s.pipe(U(p)).subscribe(()=>{for(let c of $("audio, video",e))c.pause()}),tt(e).pipe(b(()=>Na(n)),E(c=>s.next(c)),L(()=>s.complete()),m(c=>R({ref:e},c)))}).pipe(Qe(se))}function Un(e,{viewport$:t,target$:r,print$:o}){return S(...$(".annotate:not(.highlight)",e).map(n=>Cn(n,{target$:r,print$:o})),...$("pre:not(.mermaid) > code",e).map(n=>$n(n,{target$:r,print$:o})),...$("pre.mermaid",e).map(n=>In(n)),...$("table:not([class])",e).map(n=>jn(n)),...$("details",e).map(n=>Pn(n,{target$:r,print$:o})),...$("[data-tabs]",e).map(n=>Wn(n,{viewport$:t,target$:r})),...$("[title]",e).filter(()=>G("content.tooltips")).map(n=>lt(n,{viewport$:t})))}function za(e,{alert$:t}){return t.pipe(b(r=>S(I(!0),I(!1).pipe(Ge(2e3))).pipe(m(o=>({message:r,active:o})))))}function Dn(e,t){let r=P(".md-typeset",e);return C(()=>{let o=new g;return o.subscribe(({message:n,active:i})=>{e.classList.toggle("md-dialog--active",i),r.textContent=n}),za(e,t).pipe(E(n=>o.next(n)),L(()=>o.complete()),m(n=>R({ref:e},n)))})}var qa=0;function Qa(e,t){document.body.append(e);let{width:r}=ce(e);e.style.setProperty("--md-tooltip-width",`${r}px`),e.remove();let o=cr(t),n=typeof o!="undefined"?De(o):I({x:0,y:0}),i=S(et(t),kt(t)).pipe(K());return z([i,n]).pipe(m(([a,s])=>{let{x:p,y:c}=Ue(t),l=ce(t),f=t.closest("table");return f&&t.parentElement&&(p+=f.offsetLeft+t.parentElement.offsetLeft,c+=f.offsetTop+t.parentElement.offsetTop),{active:a,offset:{x:p-s.x+l.width/2-r/2,y:c-s.y+l.height+8}}}))}function Vn(e){let t=e.title;if(!t.length)return M;let r=`__tooltip_${qa++}`,o=Pt(r,"inline"),n=P(".md-typeset",o);return n.innerHTML=t,C(()=>{let i=new g;return i.subscribe({next({offset:a}){o.style.setProperty("--md-tooltip-x",`${a.x}px`),o.style.setProperty("--md-tooltip-y",`${a.y}px`)},complete(){o.style.removeProperty("--md-tooltip-x"),o.style.removeProperty("--md-tooltip-y")}}),S(i.pipe(v(({active:a})=>a)),i.pipe(_e(250),v(({active:a})=>!a))).subscribe({next({active:a}){a?(e.insertAdjacentElement("afterend",o),e.setAttribute("aria-describedby",r),e.removeAttribute("title")):(o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t))},complete(){o.remove(),e.removeAttribute("aria-describedby"),e.setAttribute("title",t)}}),i.pipe(Le(16,me)).subscribe(({active:a})=>{o.classList.toggle("md-tooltip--active",a)}),i.pipe(ct(125,me),v(()=>!!e.offsetParent),m(()=>e.offsetParent.getBoundingClientRect()),m(({x:a})=>a)).subscribe({next(a){a?o.style.setProperty("--md-tooltip-0",`${-a}px`):o.style.removeProperty("--md-tooltip-0")},complete(){o.style.removeProperty("--md-tooltip-0")}}),Qa(o,e).pipe(E(a=>i.next(a)),L(()=>i.complete()),m(a=>R({ref:e},a)))}).pipe(Qe(se))}function Ka({viewport$:e}){if(!G("header.autohide"))return I(!1);let t=e.pipe(m(({offset:{y:n}})=>n),Ye(2,1),m(([n,i])=>[nMath.abs(i-n.y)>100),m(([,[n]])=>n),K()),o=Ve("search");return z([e,o]).pipe(m(([{offset:n},i])=>n.y>400&&!i),K(),b(n=>n?r:I(!1)),Q(!1))}function Nn(e,t){return C(()=>z([ge(e),Ka(t)])).pipe(m(([{height:r},o])=>({height:r,hidden:o})),K((r,o)=>r.height===o.height&&r.hidden===o.hidden),B(1))}function zn(e,{header$:t,main$:r}){return C(()=>{let o=new g,n=o.pipe(X(),ne(!0));o.pipe(Z("active"),We(t)).subscribe(([{active:a},{hidden:s}])=>{e.classList.toggle("md-header--shadow",a&&!s),e.hidden=s});let i=ue($("[title]",e)).pipe(v(()=>G("content.tooltips")),oe(a=>Vn(a)));return r.subscribe(o),t.pipe(U(n),m(a=>R({ref:e},a)),Pe(i.pipe(U(n))))})}function Ya(e,{viewport$:t,header$:r}){return mr(e,{viewport$:t,header$:r}).pipe(m(({offset:{y:o}})=>{let{height:n}=ce(e);return{active:o>=n}}),Z("active"))}function qn(e,t){return C(()=>{let r=new g;r.subscribe({next({active:n}){e.classList.toggle("md-header__title--active",n)},complete(){e.classList.remove("md-header__title--active")}});let o=fe(".md-content h1");return typeof o=="undefined"?M:Ya(o,t).pipe(E(n=>r.next(n)),L(()=>r.complete()),m(n=>R({ref:e},n)))})}function Qn(e,{viewport$:t,header$:r}){let o=r.pipe(m(({height:i})=>i),K()),n=o.pipe(b(()=>ge(e).pipe(m(({height:i})=>({top:e.offsetTop,bottom:e.offsetTop+i})),Z("bottom"))));return z([o,n,t]).pipe(m(([i,{top:a,bottom:s},{offset:{y:p},size:{height:c}}])=>(c=Math.max(0,c-Math.max(0,a-p,i)-Math.max(0,c+p-s)),{offset:a-i,height:c,active:a-i<=p})),K((i,a)=>i.offset===a.offset&&i.height===a.height&&i.active===a.active))}function Ba(e){let t=__md_get("__palette")||{index:e.findIndex(o=>matchMedia(o.getAttribute("data-md-color-media")).matches)},r=Math.max(0,Math.min(t.index,e.length-1));return I(...e).pipe(oe(o=>d(o,"change").pipe(m(()=>o))),Q(e[r]),m(o=>({index:e.indexOf(o),color:{media:o.getAttribute("data-md-color-media"),scheme:o.getAttribute("data-md-color-scheme"),primary:o.getAttribute("data-md-color-primary"),accent:o.getAttribute("data-md-color-accent")}})),B(1))}function Kn(e){let t=$("input",e),r=x("meta",{name:"theme-color"});document.head.appendChild(r);let o=x("meta",{name:"color-scheme"});document.head.appendChild(o);let n=$t("(prefers-color-scheme: light)");return C(()=>{let i=new g;return i.subscribe(a=>{if(document.body.setAttribute("data-md-color-switching",""),a.color.media==="(prefers-color-scheme)"){let s=matchMedia("(prefers-color-scheme: light)"),p=document.querySelector(s.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");a.color.scheme=p.getAttribute("data-md-color-scheme"),a.color.primary=p.getAttribute("data-md-color-primary"),a.color.accent=p.getAttribute("data-md-color-accent")}for(let[s,p]of Object.entries(a.color))document.body.setAttribute(`data-md-color-${s}`,p);for(let s=0;sa.key==="Enter"),ee(i,(a,s)=>s)).subscribe(({index:a})=>{a=(a+1)%t.length,t[a].click(),t[a].focus()}),i.pipe(m(()=>{let a=Se("header"),s=window.getComputedStyle(a);return o.content=s.colorScheme,s.backgroundColor.match(/\d+/g).map(p=>(+p).toString(16).padStart(2,"0")).join("")})).subscribe(a=>r.content=`#${a}`),i.pipe(be(se)).subscribe(()=>{document.body.removeAttribute("data-md-color-switching")}),Ba(t).pipe(U(n.pipe(Ce(1))),st(),E(a=>i.next(a)),L(()=>i.complete()),m(a=>R({ref:e},a)))})}function Yn(e,{progress$:t}){return C(()=>{let r=new g;return r.subscribe(({value:o})=>{e.style.setProperty("--md-progress-value",`${o}`)}),t.pipe(E(o=>r.next({value:o})),L(()=>r.complete()),m(o=>({ref:e,value:o})))})}var Gr=Vt(Yr());function Ga(e){e.setAttribute("data-md-copying","");let t=e.closest("[data-copy]"),r=t?t.getAttribute("data-copy"):e.innerText;return e.removeAttribute("data-md-copying"),r.trimEnd()}function Bn({alert$:e}){Gr.default.isSupported()&&new F(t=>{new Gr.default("[data-clipboard-target], [data-clipboard-text]",{text:r=>r.getAttribute("data-clipboard-text")||Ga(P(r.getAttribute("data-clipboard-target")))}).on("success",r=>t.next(r))}).pipe(E(t=>{t.trigger.focus()}),m(()=>Ee("clipboard.copied"))).subscribe(e)}function Gn(e,t){return e.protocol=t.protocol,e.hostname=t.hostname,e}function Ja(e,t){let r=new Map;for(let o of $("url",e)){let n=P("loc",o),i=[Gn(new URL(n.textContent),t)];r.set(`${i[0]}`,i);for(let a of $("[rel=alternate]",o)){let s=a.getAttribute("href");s!=null&&i.push(Gn(new URL(s),t))}}return r}function ur(e){return mn(new URL("sitemap.xml",e)).pipe(m(t=>Ja(t,new URL(e))),ve(()=>I(new Map)))}function Xa(e,t){if(!(e.target instanceof Element))return M;let r=e.target.closest("a");if(r===null)return M;if(r.target||e.metaKey||e.ctrlKey)return M;let o=new URL(r.href);return o.search=o.hash="",t.has(`${o}`)?(e.preventDefault(),I(new URL(r.href))):M}function Jn(e){let t=new Map;for(let r of $(":scope > *",e.head))t.set(r.outerHTML,r);return t}function Xn(e){for(let t of $("[href], [src]",e))for(let r of["href","src"]){let o=t.getAttribute(r);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){t[r]=t[r];break}}return I(e)}function Za(e){for(let o of["[data-md-component=announce]","[data-md-component=container]","[data-md-component=header-topic]","[data-md-component=outdated]","[data-md-component=logo]","[data-md-component=skip]",...G("navigation.tabs.sticky")?["[data-md-component=tabs]"]:[]]){let n=fe(o),i=fe(o,e);typeof n!="undefined"&&typeof i!="undefined"&&n.replaceWith(i)}let t=Jn(document);for(let[o,n]of Jn(e))t.has(o)?t.delete(o):document.head.appendChild(n);for(let o of t.values()){let n=o.getAttribute("name");n!=="theme-color"&&n!=="color-scheme"&&o.remove()}let r=Se("container");return je($("script",r)).pipe(b(o=>{let n=e.createElement("script");if(o.src){for(let i of o.getAttributeNames())n.setAttribute(i,o.getAttribute(i));return o.replaceWith(n),new F(i=>{n.onload=()=>i.complete()})}else return n.textContent=o.textContent,o.replaceWith(n),M}),X(),ne(document))}function Zn({location$:e,viewport$:t,progress$:r}){let o=ye();if(location.protocol==="file:")return M;let n=ur(o.base);I(document).subscribe(Xn);let i=d(document.body,"click").pipe(We(n),b(([p,c])=>Xa(p,c)),pe()),a=d(window,"popstate").pipe(m(xe),pe());i.pipe(ee(t)).subscribe(([p,{offset:c}])=>{history.replaceState(c,""),history.pushState(null,"",p)}),S(i,a).subscribe(e);let s=e.pipe(Z("pathname"),b(p=>ln(p,{progress$:r}).pipe(ve(()=>(pt(p,!0),M)))),b(Xn),b(Za),pe());return S(s.pipe(ee(e,(p,c)=>c)),s.pipe(b(()=>e),Z("pathname"),b(()=>e),Z("hash")),e.pipe(K((p,c)=>p.pathname===c.pathname&&p.hash===c.hash),b(()=>i),E(()=>history.back()))).subscribe(p=>{var c,l;history.state!==null||!p.hash?window.scrollTo(0,(l=(c=history.state)==null?void 0:c.y)!=null?l:0):(history.scrollRestoration="auto",sn(p.hash),history.scrollRestoration="manual")}),e.subscribe(()=>{history.scrollRestoration="manual"}),d(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}),t.pipe(Z("offset"),_e(100)).subscribe(({offset:p})=>{history.replaceState(p,"")}),s}var ri=Vt(ti());function oi(e){let t=e.separator.split("|").map(n=>n.replace(/(\(\?[!=<][^)]+\))/g,"").length===0?"\uFFFD":n).join("|"),r=new RegExp(t,"img"),o=(n,i,a)=>`${i}${a}`;return n=>{n=n.replace(/[\s*+\-:~^]+/g," ").trim();let i=new RegExp(`(^|${e.separator}|)(${n.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(r,"|")})`,"img");return a=>(0,ri.default)(a).replace(i,o).replace(/<\/mark>(\s+)]*>/img,"$1")}}function It(e){return e.type===1}function dr(e){return e.type===3}function ni(e,t){let r=vn(e);return S(I(location.protocol!=="file:"),Ve("search")).pipe(Ae(o=>o),b(()=>t)).subscribe(({config:o,docs:n})=>r.next({type:0,data:{config:o,docs:n,options:{suggest:G("search.suggest")}}})),r}function ii({document$:e}){let t=ye(),r=Ne(new URL("../versions.json",t.base)).pipe(ve(()=>M)),o=r.pipe(m(n=>{let[,i]=t.base.match(/([^/]+)\/?$/);return n.find(({version:a,aliases:s})=>a===i||s.includes(i))||n[0]}));r.pipe(m(n=>new Map(n.map(i=>[`${new URL(`../${i.version}/`,t.base)}`,i]))),b(n=>d(document.body,"click").pipe(v(i=>!i.metaKey&&!i.ctrlKey),ee(o),b(([i,a])=>{if(i.target instanceof Element){let s=i.target.closest("a");if(s&&!s.target&&n.has(s.href)){let p=s.href;return!i.target.closest(".md-version")&&n.get(p)===a?M:(i.preventDefault(),I(p))}}return M}),b(i=>ur(new URL(i)).pipe(m(a=>{let p=xe().href.replace(t.base,i);return a.has(p.split("#")[0])?new URL(p):new URL(i)})))))).subscribe(n=>pt(n,!0)),z([r,o]).subscribe(([n,i])=>{P(".md-header__topic").appendChild(Mn(n,i))}),e.pipe(b(()=>o)).subscribe(n=>{var a;let i=__md_get("__outdated",sessionStorage);if(i===null){i=!0;let s=((a=t.version)==null?void 0:a.default)||"latest";Array.isArray(s)||(s=[s]);e:for(let p of s)for(let c of n.aliases.concat(n.version))if(new RegExp(p,"i").test(c)){i=!1;break e}__md_set("__outdated",i,sessionStorage)}if(i)for(let s of ae("outdated"))s.hidden=!1})}function ns(e,{worker$:t}){let{searchParams:r}=xe();r.has("q")&&(Je("search",!0),e.value=r.get("q"),e.focus(),Ve("search").pipe(Ae(i=>!i)).subscribe(()=>{let i=xe();i.searchParams.delete("q"),history.replaceState({},"",`${i}`)}));let o=et(e),n=S(t.pipe(Ae(It)),d(e,"keyup"),o).pipe(m(()=>e.value),K());return z([n,o]).pipe(m(([i,a])=>({value:i,focus:a})),B(1))}function ai(e,{worker$:t}){let r=new g,o=r.pipe(X(),ne(!0));z([t.pipe(Ae(It)),r],(i,a)=>a).pipe(Z("value")).subscribe(({value:i})=>t.next({type:2,data:i})),r.pipe(Z("focus")).subscribe(({focus:i})=>{i&&Je("search",i)}),d(e.form,"reset").pipe(U(o)).subscribe(()=>e.focus());let n=P("header [for=__search]");return d(n,"click").subscribe(()=>e.focus()),ns(e,{worker$:t}).pipe(E(i=>r.next(i)),L(()=>r.complete()),m(i=>R({ref:e},i)),B(1))}function si(e,{worker$:t,query$:r}){let o=new g,n=tn(e.parentElement).pipe(v(Boolean)),i=e.parentElement,a=P(":scope > :first-child",e),s=P(":scope > :last-child",e);Ve("search").subscribe(l=>s.setAttribute("role",l?"list":"presentation")),o.pipe(ee(r),Ur(t.pipe(Ae(It)))).subscribe(([{items:l},{value:f}])=>{switch(l.length){case 0:a.textContent=f.length?Ee("search.result.none"):Ee("search.result.placeholder");break;case 1:a.textContent=Ee("search.result.one");break;default:let u=sr(l.length);a.textContent=Ee("search.result.other",u)}});let p=o.pipe(E(()=>s.innerHTML=""),b(({items:l})=>S(I(...l.slice(0,10)),I(...l.slice(10)).pipe(Ye(4),Vr(n),b(([f])=>f)))),m(Tn),pe());return p.subscribe(l=>s.appendChild(l)),p.pipe(oe(l=>{let f=fe("details",l);return typeof f=="undefined"?M:d(f,"toggle").pipe(U(o),m(()=>f))})).subscribe(l=>{l.open===!1&&l.offsetTop<=i.scrollTop&&i.scrollTo({top:l.offsetTop})}),t.pipe(v(dr),m(({data:l})=>l)).pipe(E(l=>o.next(l)),L(()=>o.complete()),m(l=>R({ref:e},l)))}function is(e,{query$:t}){return t.pipe(m(({value:r})=>{let o=xe();return o.hash="",r=r.replace(/\s+/g,"+").replace(/&/g,"%26").replace(/=/g,"%3D"),o.search=`q=${r}`,{url:o}}))}function ci(e,t){let r=new g,o=r.pipe(X(),ne(!0));return r.subscribe(({url:n})=>{e.setAttribute("data-clipboard-text",e.href),e.href=`${n}`}),d(e,"click").pipe(U(o)).subscribe(n=>n.preventDefault()),is(e,t).pipe(E(n=>r.next(n)),L(()=>r.complete()),m(n=>R({ref:e},n)))}function pi(e,{worker$:t,keyboard$:r}){let o=new g,n=Se("search-query"),i=S(d(n,"keydown"),d(n,"focus")).pipe(be(se),m(()=>n.value),K());return o.pipe(We(i),m(([{suggest:s},p])=>{let c=p.split(/([\s-]+)/);if(s!=null&&s.length&&c[c.length-1]){let l=s[s.length-1];l.startsWith(c[c.length-1])&&(c[c.length-1]=l)}else c.length=0;return c})).subscribe(s=>e.innerHTML=s.join("").replace(/\s/g," ")),r.pipe(v(({mode:s})=>s==="search")).subscribe(s=>{switch(s.type){case"ArrowRight":e.innerText.length&&n.selectionStart===n.value.length&&(n.value=e.innerText);break}}),t.pipe(v(dr),m(({data:s})=>s)).pipe(E(s=>o.next(s)),L(()=>o.complete()),m(()=>({ref:e})))}function li(e,{index$:t,keyboard$:r}){let o=ye();try{let n=ni(o.search,t),i=Se("search-query",e),a=Se("search-result",e);d(e,"click").pipe(v(({target:p})=>p instanceof Element&&!!p.closest("a"))).subscribe(()=>Je("search",!1)),r.pipe(v(({mode:p})=>p==="search")).subscribe(p=>{let c=Re();switch(p.type){case"Enter":if(c===i){let l=new Map;for(let f of $(":first-child [href]",a)){let u=f.firstElementChild;l.set(f,parseFloat(u.getAttribute("data-md-score")))}if(l.size){let[[f]]=[...l].sort(([,u],[,h])=>h-u);f.click()}p.claim()}break;case"Escape":case"Tab":Je("search",!1),i.blur();break;case"ArrowUp":case"ArrowDown":if(typeof c=="undefined")i.focus();else{let l=[i,...$(":not(details) > [href], summary, details[open] [href]",a)],f=Math.max(0,(Math.max(0,l.indexOf(c))+l.length+(p.type==="ArrowUp"?-1:1))%l.length);l[f].focus()}p.claim();break;default:i!==Re()&&i.focus()}}),r.pipe(v(({mode:p})=>p==="global")).subscribe(p=>{switch(p.type){case"f":case"s":case"/":i.focus(),i.select(),p.claim();break}});let s=ai(i,{worker$:n});return S(s,si(a,{worker$:n,query$:s})).pipe(Pe(...ae("search-share",e).map(p=>ci(p,{query$:s})),...ae("search-suggest",e).map(p=>pi(p,{worker$:n,keyboard$:r}))))}catch(n){return e.hidden=!0,Ke}}function mi(e,{index$:t,location$:r}){return z([t,r.pipe(Q(xe()),v(o=>!!o.searchParams.get("h")))]).pipe(m(([o,n])=>oi(o.config)(n.searchParams.get("h"))),m(o=>{var a;let n=new Map,i=document.createNodeIterator(e,NodeFilter.SHOW_TEXT);for(let s=i.nextNode();s;s=i.nextNode())if((a=s.parentElement)!=null&&a.offsetHeight){let p=s.textContent,c=o(p);c.length>p.length&&n.set(s,c)}for(let[s,p]of n){let{childNodes:c}=x("span",null,p);s.replaceWith(...Array.from(c))}return{ref:e,nodes:n}}))}function as(e,{viewport$:t,main$:r}){let o=e.closest(".md-grid"),n=o.offsetTop-o.parentElement.offsetTop;return z([r,t]).pipe(m(([{offset:i,height:a},{offset:{y:s}}])=>(a=a+Math.min(n,Math.max(0,s-i))-n,{height:a,locked:s>=i+n})),K((i,a)=>i.height===a.height&&i.locked===a.locked))}function Jr(e,o){var n=o,{header$:t}=n,r=io(n,["header$"]);let i=P(".md-sidebar__scrollwrap",e),{y:a}=Ue(i);return C(()=>{let s=new g,p=s.pipe(X(),ne(!0)),c=s.pipe(Le(0,me));return c.pipe(ee(t)).subscribe({next([{height:l},{height:f}]){i.style.height=`${l-2*a}px`,e.style.top=`${f}px`},complete(){i.style.height="",e.style.top=""}}),c.pipe(Ae()).subscribe(()=>{for(let l of $(".md-nav__link--active[href]",e)){if(!l.clientHeight)continue;let f=l.closest(".md-sidebar__scrollwrap");if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:h}=ce(f);f.scrollTo({top:u-h/2})}}}),ue($("label[tabindex]",e)).pipe(oe(l=>d(l,"click").pipe(be(se),m(()=>l),U(p)))).subscribe(l=>{let f=P(`[id="${l.htmlFor}"]`);P(`[aria-labelledby="${l.id}"]`).setAttribute("aria-expanded",`${f.checked}`)}),as(e,r).pipe(E(l=>s.next(l)),L(()=>s.complete()),m(l=>R({ref:e},l)))})}function fi(e,t){if(typeof t!="undefined"){let r=`https://api.github.com/repos/${e}/${t}`;return Ct(Ne(`${r}/releases/latest`).pipe(ve(()=>M),m(o=>({version:o.tag_name})),Be({})),Ne(r).pipe(ve(()=>M),m(o=>({stars:o.stargazers_count,forks:o.forks_count})),Be({}))).pipe(m(([o,n])=>R(R({},o),n)))}else{let r=`https://api.github.com/users/${e}`;return Ne(r).pipe(m(o=>({repositories:o.public_repos})),Be({}))}}function ui(e,t){let r=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return Ne(r).pipe(ve(()=>M),m(({star_count:o,forks_count:n})=>({stars:o,forks:n})),Be({}))}function di(e){let t=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);if(t){let[,r,o]=t;return fi(r,o)}if(t=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i),t){let[,r,o]=t;return ui(r,o)}return M}var ss;function cs(e){return ss||(ss=C(()=>{let t=__md_get("__source",sessionStorage);if(t)return I(t);if(ae("consent").length){let o=__md_get("__consent");if(!(o&&o.github))return M}return di(e.href).pipe(E(o=>__md_set("__source",o,sessionStorage)))}).pipe(ve(()=>M),v(t=>Object.keys(t).length>0),m(t=>({facts:t})),B(1)))}function hi(e){let t=P(":scope > :last-child",e);return C(()=>{let r=new g;return r.subscribe(({facts:o})=>{t.appendChild(Sn(o)),t.classList.add("md-source__repository--active")}),cs(e).pipe(E(o=>r.next(o)),L(()=>r.complete()),m(o=>R({ref:e},o)))})}function ps(e,{viewport$:t,header$:r}){return ge(document.body).pipe(b(()=>mr(e,{header$:r,viewport$:t})),m(({offset:{y:o}})=>({hidden:o>=10})),Z("hidden"))}function bi(e,t){return C(()=>{let r=new g;return r.subscribe({next({hidden:o}){e.hidden=o},complete(){e.hidden=!1}}),(G("navigation.tabs.sticky")?I({hidden:!1}):ps(e,t)).pipe(E(o=>r.next(o)),L(()=>r.complete()),m(o=>R({ref:e},o)))})}function ls(e,{viewport$:t,header$:r}){let o=new Map,n=$(".md-nav__link",e);for(let s of n){let p=decodeURIComponent(s.hash.substring(1)),c=fe(`[id="${p}"]`);typeof c!="undefined"&&o.set(s,c)}let i=r.pipe(Z("height"),m(({height:s})=>{let p=Se("main"),c=P(":scope > :first-child",p);return s+.8*(c.offsetTop-p.offsetTop)}),pe());return ge(document.body).pipe(Z("height"),b(s=>C(()=>{let p=[];return I([...o].reduce((c,[l,f])=>{for(;p.length&&o.get(p[p.length-1]).tagName>=f.tagName;)p.pop();let u=f.offsetTop;for(;!u&&f.parentElement;)f=f.parentElement,u=f.offsetTop;let h=f.offsetParent;for(;h;h=h.offsetParent)u+=h.offsetTop;return c.set([...p=[...p,l]].reverse(),u)},new Map))}).pipe(m(p=>new Map([...p].sort(([,c],[,l])=>c-l))),We(i),b(([p,c])=>t.pipe(jr(([l,f],{offset:{y:u},size:h})=>{let w=u+h.height>=Math.floor(s.height);for(;f.length;){let[,A]=f[0];if(A-c=u&&!w)f=[l.pop(),...f];else break}return[l,f]},[[],[...p]]),K((l,f)=>l[0]===f[0]&&l[1]===f[1])))))).pipe(m(([s,p])=>({prev:s.map(([c])=>c),next:p.map(([c])=>c)})),Q({prev:[],next:[]}),Ye(2,1),m(([s,p])=>s.prev.length{let i=new g,a=i.pipe(X(),ne(!0));if(i.subscribe(({prev:s,next:p})=>{for(let[c]of p)c.classList.remove("md-nav__link--passed"),c.classList.remove("md-nav__link--active");for(let[c,[l]]of s.entries())l.classList.add("md-nav__link--passed"),l.classList.toggle("md-nav__link--active",c===s.length-1)}),G("toc.follow")){let s=S(t.pipe(_e(1),m(()=>{})),t.pipe(_e(250),m(()=>"smooth")));i.pipe(v(({prev:p})=>p.length>0),We(o.pipe(be(se))),ee(s)).subscribe(([[{prev:p}],c])=>{let[l]=p[p.length-1];if(l.offsetHeight){let f=cr(l);if(typeof f!="undefined"){let u=l.offsetTop-f.offsetTop,{height:h}=ce(f);f.scrollTo({top:u-h/2,behavior:c})}}})}return G("navigation.tracking")&&t.pipe(U(a),Z("offset"),_e(250),Ce(1),U(n.pipe(Ce(1))),st({delay:250}),ee(i)).subscribe(([,{prev:s}])=>{let p=xe(),c=s[s.length-1];if(c&&c.length){let[l]=c,{hash:f}=new URL(l.href);p.hash!==f&&(p.hash=f,history.replaceState({},"",`${p}`))}else p.hash="",history.replaceState({},"",`${p}`)}),ls(e,{viewport$:t,header$:r}).pipe(E(s=>i.next(s)),L(()=>i.complete()),m(s=>R({ref:e},s)))})}function ms(e,{viewport$:t,main$:r,target$:o}){let n=t.pipe(m(({offset:{y:a}})=>a),Ye(2,1),m(([a,s])=>a>s&&s>0),K()),i=r.pipe(m(({active:a})=>a));return z([i,n]).pipe(m(([a,s])=>!(a&&s)),K(),U(o.pipe(Ce(1))),ne(!0),st({delay:250}),m(a=>({hidden:a})))}function gi(e,{viewport$:t,header$:r,main$:o,target$:n}){let i=new g,a=i.pipe(X(),ne(!0));return i.subscribe({next({hidden:s}){e.hidden=s,s?(e.setAttribute("tabindex","-1"),e.blur()):e.removeAttribute("tabindex")},complete(){e.style.top="",e.hidden=!0,e.removeAttribute("tabindex")}}),r.pipe(U(a),Z("height")).subscribe(({height:s})=>{e.style.top=`${s+16}px`}),d(e,"click").subscribe(s=>{s.preventDefault(),window.scrollTo({top:0})}),ms(e,{viewport$:t,main$:o,target$:n}).pipe(E(s=>i.next(s)),L(()=>i.complete()),m(s=>R({ref:e},s)))}function xi({document$:e,viewport$:t}){e.pipe(b(()=>$(".md-ellipsis")),oe(r=>tt(r).pipe(U(e.pipe(Ce(1))),v(o=>o),m(()=>r),Te(1))),v(r=>r.offsetWidth{let o=r.innerText,n=r.closest("a")||r;return n.title=o,lt(n,{viewport$:t}).pipe(U(e.pipe(Ce(1))),L(()=>n.removeAttribute("title")))})).subscribe(),e.pipe(b(()=>$(".md-status")),oe(r=>lt(r,{viewport$:t}))).subscribe()}function yi({document$:e,tablet$:t}){e.pipe(b(()=>$(".md-toggle--indeterminate")),E(r=>{r.indeterminate=!0,r.checked=!1}),oe(r=>d(r,"change").pipe(Dr(()=>r.classList.contains("md-toggle--indeterminate")),m(()=>r))),ee(t)).subscribe(([r,o])=>{r.classList.remove("md-toggle--indeterminate"),o&&(r.checked=!1)})}function fs(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}function Ei({document$:e}){e.pipe(b(()=>$("[data-md-scrollfix]")),E(t=>t.removeAttribute("data-md-scrollfix")),v(fs),oe(t=>d(t,"touchstart").pipe(m(()=>t)))).subscribe(t=>{let r=t.scrollTop;r===0?t.scrollTop=1:r+t.offsetHeight===t.scrollHeight&&(t.scrollTop=r-1)})}function wi({viewport$:e,tablet$:t}){z([Ve("search"),t]).pipe(m(([r,o])=>r&&!o),b(r=>I(r).pipe(Ge(r?400:100))),ee(e)).subscribe(([r,{offset:{y:o}}])=>{if(r)document.body.setAttribute("data-md-scrolllock",""),document.body.style.top=`-${o}px`;else{let n=-1*parseInt(document.body.style.top,10);document.body.removeAttribute("data-md-scrolllock"),document.body.style.top="",n&&window.scrollTo(0,n)}})}Object.entries||(Object.entries=function(e){let t=[];for(let r of Object.keys(e))t.push([r,e[r]]);return t});Object.values||(Object.values=function(e){let t=[];for(let r of Object.keys(e))t.push(e[r]);return t});typeof Element!="undefined"&&(Element.prototype.scrollTo||(Element.prototype.scrollTo=function(e,t){typeof e=="object"?(this.scrollLeft=e.left,this.scrollTop=e.top):(this.scrollLeft=e,this.scrollTop=t)}),Element.prototype.replaceWith||(Element.prototype.replaceWith=function(...e){let t=this.parentNode;if(t){e.length===0&&t.removeChild(this);for(let r=e.length-1;r>=0;r--){let o=e[r];typeof o=="string"?o=document.createTextNode(o):o.parentNode&&o.parentNode.removeChild(o),r?t.insertBefore(this.previousSibling,o):t.replaceChild(o,this)}}}));function us(){return location.protocol==="file:"?wt(`${new URL("search/search_index.js",Xr.base)}`).pipe(m(()=>__index),B(1)):Ne(new URL("search/search_index.json",Xr.base))}document.documentElement.classList.remove("no-js");document.documentElement.classList.add("js");var ot=Yo(),jt=nn(),Ot=cn(jt),Zr=on(),Oe=bn(),hr=$t("(min-width: 960px)"),Si=$t("(min-width: 1220px)"),Oi=pn(),Xr=ye(),Mi=document.forms.namedItem("search")?us():Ke,eo=new g;Bn({alert$:eo});var to=new g;G("navigation.instant")&&Zn({location$:jt,viewport$:Oe,progress$:to}).subscribe(ot);var Ti;((Ti=Xr.version)==null?void 0:Ti.provider)==="mike"&&ii({document$:ot});S(jt,Ot).pipe(Ge(125)).subscribe(()=>{Je("drawer",!1),Je("search",!1)});Zr.pipe(v(({mode:e})=>e==="global")).subscribe(e=>{switch(e.type){case"p":case",":let t=fe("link[rel=prev]");typeof t!="undefined"&&pt(t);break;case"n":case".":let r=fe("link[rel=next]");typeof r!="undefined"&&pt(r);break;case"Enter":let o=Re();o instanceof HTMLLabelElement&&o.click()}});xi({viewport$:Oe,document$:ot});yi({document$:ot,tablet$:hr});Ei({document$:ot});wi({viewport$:Oe,tablet$:hr});var rt=Nn(Se("header"),{viewport$:Oe}),Ft=ot.pipe(m(()=>Se("main")),b(e=>Qn(e,{viewport$:Oe,header$:rt})),B(1)),ds=S(...ae("consent").map(e=>xn(e,{target$:Ot})),...ae("dialog").map(e=>Dn(e,{alert$:eo})),...ae("header").map(e=>zn(e,{viewport$:Oe,header$:rt,main$:Ft})),...ae("palette").map(e=>Kn(e)),...ae("progress").map(e=>Yn(e,{progress$:to})),...ae("search").map(e=>li(e,{index$:Mi,keyboard$:Zr})),...ae("source").map(e=>hi(e))),hs=C(()=>S(...ae("announce").map(e=>gn(e)),...ae("content").map(e=>Un(e,{viewport$:Oe,target$:Ot,print$:Oi})),...ae("content").map(e=>G("search.highlight")?mi(e,{index$:Mi,location$:jt}):M),...ae("header-title").map(e=>qn(e,{viewport$:Oe,header$:rt})),...ae("sidebar").map(e=>e.getAttribute("data-md-type")==="navigation"?Nr(Si,()=>Jr(e,{viewport$:Oe,header$:rt,main$:Ft})):Nr(hr,()=>Jr(e,{viewport$:Oe,header$:rt,main$:Ft}))),...ae("tabs").map(e=>bi(e,{viewport$:Oe,header$:rt})),...ae("toc").map(e=>vi(e,{viewport$:Oe,header$:rt,main$:Ft,target$:Ot})),...ae("top").map(e=>gi(e,{viewport$:Oe,header$:rt,main$:Ft,target$:Ot})))),Li=ot.pipe(b(()=>hs),Pe(ds),B(1));Li.subscribe();window.document$=ot;window.location$=jt;window.target$=Ot;window.keyboard$=Zr;window.viewport$=Oe;window.tablet$=hr;window.screen$=Si;window.print$=Oi;window.alert$=eo;window.progress$=to;window.component$=Li;})(); +//# sourceMappingURL=bundle.081f42fc.min.js.map + diff --git a/1.2/assets/javascripts/bundle.081f42fc.min.js.map b/1.2/assets/javascripts/bundle.081f42fc.min.js.map new file mode 100644 index 000000000..e055db5ac --- /dev/null +++ b/1.2/assets/javascripts/bundle.081f42fc.min.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["node_modules/focus-visible/dist/focus-visible.js", "node_modules/clipboard/dist/clipboard.js", "node_modules/escape-html/index.js", "src/templates/assets/javascripts/bundle.ts", "node_modules/rxjs/node_modules/tslib/tslib.es6.js", "node_modules/rxjs/src/internal/util/isFunction.ts", "node_modules/rxjs/src/internal/util/createErrorClass.ts", "node_modules/rxjs/src/internal/util/UnsubscriptionError.ts", "node_modules/rxjs/src/internal/util/arrRemove.ts", "node_modules/rxjs/src/internal/Subscription.ts", "node_modules/rxjs/src/internal/config.ts", "node_modules/rxjs/src/internal/scheduler/timeoutProvider.ts", "node_modules/rxjs/src/internal/util/reportUnhandledError.ts", "node_modules/rxjs/src/internal/util/noop.ts", "node_modules/rxjs/src/internal/NotificationFactories.ts", "node_modules/rxjs/src/internal/util/errorContext.ts", "node_modules/rxjs/src/internal/Subscriber.ts", "node_modules/rxjs/src/internal/symbol/observable.ts", "node_modules/rxjs/src/internal/util/identity.ts", "node_modules/rxjs/src/internal/util/pipe.ts", "node_modules/rxjs/src/internal/Observable.ts", "node_modules/rxjs/src/internal/util/lift.ts", "node_modules/rxjs/src/internal/operators/OperatorSubscriber.ts", "node_modules/rxjs/src/internal/scheduler/animationFrameProvider.ts", "node_modules/rxjs/src/internal/util/ObjectUnsubscribedError.ts", "node_modules/rxjs/src/internal/Subject.ts", "node_modules/rxjs/src/internal/BehaviorSubject.ts", "node_modules/rxjs/src/internal/scheduler/dateTimestampProvider.ts", "node_modules/rxjs/src/internal/ReplaySubject.ts", "node_modules/rxjs/src/internal/scheduler/Action.ts", "node_modules/rxjs/src/internal/scheduler/intervalProvider.ts", "node_modules/rxjs/src/internal/scheduler/AsyncAction.ts", "node_modules/rxjs/src/internal/Scheduler.ts", "node_modules/rxjs/src/internal/scheduler/AsyncScheduler.ts", "node_modules/rxjs/src/internal/scheduler/async.ts", "node_modules/rxjs/src/internal/scheduler/QueueAction.ts", "node_modules/rxjs/src/internal/scheduler/QueueScheduler.ts", "node_modules/rxjs/src/internal/scheduler/queue.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameAction.ts", "node_modules/rxjs/src/internal/scheduler/AnimationFrameScheduler.ts", "node_modules/rxjs/src/internal/scheduler/animationFrame.ts", "node_modules/rxjs/src/internal/observable/empty.ts", "node_modules/rxjs/src/internal/util/isScheduler.ts", "node_modules/rxjs/src/internal/util/args.ts", "node_modules/rxjs/src/internal/util/isArrayLike.ts", "node_modules/rxjs/src/internal/util/isPromise.ts", "node_modules/rxjs/src/internal/util/isInteropObservable.ts", "node_modules/rxjs/src/internal/util/isAsyncIterable.ts", "node_modules/rxjs/src/internal/util/throwUnobservableError.ts", "node_modules/rxjs/src/internal/symbol/iterator.ts", "node_modules/rxjs/src/internal/util/isIterable.ts", "node_modules/rxjs/src/internal/util/isReadableStreamLike.ts", "node_modules/rxjs/src/internal/observable/innerFrom.ts", "node_modules/rxjs/src/internal/util/executeSchedule.ts", "node_modules/rxjs/src/internal/operators/observeOn.ts", "node_modules/rxjs/src/internal/operators/subscribeOn.ts", "node_modules/rxjs/src/internal/scheduled/scheduleObservable.ts", "node_modules/rxjs/src/internal/scheduled/schedulePromise.ts", "node_modules/rxjs/src/internal/scheduled/scheduleArray.ts", "node_modules/rxjs/src/internal/scheduled/scheduleIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleAsyncIterable.ts", "node_modules/rxjs/src/internal/scheduled/scheduleReadableStreamLike.ts", "node_modules/rxjs/src/internal/scheduled/scheduled.ts", "node_modules/rxjs/src/internal/observable/from.ts", "node_modules/rxjs/src/internal/observable/of.ts", "node_modules/rxjs/src/internal/observable/throwError.ts", "node_modules/rxjs/src/internal/util/EmptyError.ts", "node_modules/rxjs/src/internal/util/isDate.ts", "node_modules/rxjs/src/internal/operators/map.ts", "node_modules/rxjs/src/internal/util/mapOneOrManyArgs.ts", "node_modules/rxjs/src/internal/util/argsArgArrayOrObject.ts", "node_modules/rxjs/src/internal/util/createObject.ts", "node_modules/rxjs/src/internal/observable/combineLatest.ts", "node_modules/rxjs/src/internal/operators/mergeInternals.ts", "node_modules/rxjs/src/internal/operators/mergeMap.ts", "node_modules/rxjs/src/internal/operators/mergeAll.ts", "node_modules/rxjs/src/internal/operators/concatAll.ts", "node_modules/rxjs/src/internal/observable/concat.ts", "node_modules/rxjs/src/internal/observable/defer.ts", "node_modules/rxjs/src/internal/observable/fromEvent.ts", "node_modules/rxjs/src/internal/observable/fromEventPattern.ts", "node_modules/rxjs/src/internal/observable/timer.ts", "node_modules/rxjs/src/internal/observable/merge.ts", "node_modules/rxjs/src/internal/observable/never.ts", "node_modules/rxjs/src/internal/util/argsOrArgArray.ts", "node_modules/rxjs/src/internal/operators/filter.ts", "node_modules/rxjs/src/internal/observable/zip.ts", "node_modules/rxjs/src/internal/operators/audit.ts", "node_modules/rxjs/src/internal/operators/auditTime.ts", "node_modules/rxjs/src/internal/operators/bufferCount.ts", "node_modules/rxjs/src/internal/operators/catchError.ts", "node_modules/rxjs/src/internal/operators/scanInternals.ts", "node_modules/rxjs/src/internal/operators/combineLatest.ts", "node_modules/rxjs/src/internal/operators/combineLatestWith.ts", "node_modules/rxjs/src/internal/operators/debounce.ts", "node_modules/rxjs/src/internal/operators/debounceTime.ts", "node_modules/rxjs/src/internal/operators/defaultIfEmpty.ts", "node_modules/rxjs/src/internal/operators/take.ts", "node_modules/rxjs/src/internal/operators/ignoreElements.ts", "node_modules/rxjs/src/internal/operators/mapTo.ts", "node_modules/rxjs/src/internal/operators/delayWhen.ts", "node_modules/rxjs/src/internal/operators/delay.ts", "node_modules/rxjs/src/internal/operators/distinctUntilChanged.ts", "node_modules/rxjs/src/internal/operators/distinctUntilKeyChanged.ts", "node_modules/rxjs/src/internal/operators/throwIfEmpty.ts", "node_modules/rxjs/src/internal/operators/endWith.ts", "node_modules/rxjs/src/internal/operators/finalize.ts", "node_modules/rxjs/src/internal/operators/first.ts", "node_modules/rxjs/src/internal/operators/takeLast.ts", "node_modules/rxjs/src/internal/operators/merge.ts", "node_modules/rxjs/src/internal/operators/mergeWith.ts", "node_modules/rxjs/src/internal/operators/repeat.ts", "node_modules/rxjs/src/internal/operators/scan.ts", "node_modules/rxjs/src/internal/operators/share.ts", "node_modules/rxjs/src/internal/operators/shareReplay.ts", "node_modules/rxjs/src/internal/operators/skip.ts", "node_modules/rxjs/src/internal/operators/skipUntil.ts", "node_modules/rxjs/src/internal/operators/startWith.ts", "node_modules/rxjs/src/internal/operators/switchMap.ts", "node_modules/rxjs/src/internal/operators/takeUntil.ts", "node_modules/rxjs/src/internal/operators/takeWhile.ts", "node_modules/rxjs/src/internal/operators/tap.ts", "node_modules/rxjs/src/internal/operators/throttle.ts", "node_modules/rxjs/src/internal/operators/throttleTime.ts", "node_modules/rxjs/src/internal/operators/withLatestFrom.ts", "node_modules/rxjs/src/internal/operators/zip.ts", "node_modules/rxjs/src/internal/operators/zipWith.ts", "src/templates/assets/javascripts/browser/document/index.ts", "src/templates/assets/javascripts/browser/element/_/index.ts", "src/templates/assets/javascripts/browser/element/focus/index.ts", "src/templates/assets/javascripts/browser/element/hover/index.ts", "src/templates/assets/javascripts/utilities/h/index.ts", "src/templates/assets/javascripts/utilities/round/index.ts", "src/templates/assets/javascripts/browser/script/index.ts", "src/templates/assets/javascripts/browser/element/size/_/index.ts", "src/templates/assets/javascripts/browser/element/size/content/index.ts", "src/templates/assets/javascripts/browser/element/offset/_/index.ts", "src/templates/assets/javascripts/browser/element/offset/content/index.ts", "src/templates/assets/javascripts/browser/element/visibility/index.ts", "src/templates/assets/javascripts/browser/toggle/index.ts", "src/templates/assets/javascripts/browser/keyboard/index.ts", "src/templates/assets/javascripts/browser/location/_/index.ts", "src/templates/assets/javascripts/browser/location/hash/index.ts", "src/templates/assets/javascripts/browser/media/index.ts", "src/templates/assets/javascripts/browser/request/index.ts", "src/templates/assets/javascripts/browser/viewport/offset/index.ts", "src/templates/assets/javascripts/browser/viewport/size/index.ts", "src/templates/assets/javascripts/browser/viewport/_/index.ts", "src/templates/assets/javascripts/browser/viewport/at/index.ts", "src/templates/assets/javascripts/browser/worker/index.ts", "src/templates/assets/javascripts/_/index.ts", "src/templates/assets/javascripts/components/_/index.ts", "src/templates/assets/javascripts/components/announce/index.ts", "src/templates/assets/javascripts/components/consent/index.ts", "src/templates/assets/javascripts/templates/tooltip/index.tsx", "src/templates/assets/javascripts/templates/annotation/index.tsx", "src/templates/assets/javascripts/templates/clipboard/index.tsx", "src/templates/assets/javascripts/templates/search/index.tsx", "src/templates/assets/javascripts/templates/source/index.tsx", "src/templates/assets/javascripts/templates/tabbed/index.tsx", "src/templates/assets/javascripts/templates/table/index.tsx", "src/templates/assets/javascripts/templates/version/index.tsx", "src/templates/assets/javascripts/components/tooltip2/index.ts", "src/templates/assets/javascripts/components/content/annotation/_/index.ts", "src/templates/assets/javascripts/components/content/annotation/list/index.ts", "src/templates/assets/javascripts/components/content/annotation/block/index.ts", "src/templates/assets/javascripts/components/content/code/_/index.ts", "src/templates/assets/javascripts/components/content/details/index.ts", "src/templates/assets/javascripts/components/content/mermaid/index.css", "src/templates/assets/javascripts/components/content/mermaid/index.ts", "src/templates/assets/javascripts/components/content/table/index.ts", "src/templates/assets/javascripts/components/content/tabs/index.ts", "src/templates/assets/javascripts/components/content/_/index.ts", "src/templates/assets/javascripts/components/dialog/index.ts", "src/templates/assets/javascripts/components/tooltip/index.ts", "src/templates/assets/javascripts/components/header/_/index.ts", "src/templates/assets/javascripts/components/header/title/index.ts", "src/templates/assets/javascripts/components/main/index.ts", "src/templates/assets/javascripts/components/palette/index.ts", "src/templates/assets/javascripts/components/progress/index.ts", "src/templates/assets/javascripts/integrations/clipboard/index.ts", "src/templates/assets/javascripts/integrations/sitemap/index.ts", "src/templates/assets/javascripts/integrations/instant/index.ts", "src/templates/assets/javascripts/integrations/search/highlighter/index.ts", "src/templates/assets/javascripts/integrations/search/worker/message/index.ts", "src/templates/assets/javascripts/integrations/search/worker/_/index.ts", "src/templates/assets/javascripts/integrations/version/index.ts", "src/templates/assets/javascripts/components/search/query/index.ts", "src/templates/assets/javascripts/components/search/result/index.ts", "src/templates/assets/javascripts/components/search/share/index.ts", "src/templates/assets/javascripts/components/search/suggest/index.ts", "src/templates/assets/javascripts/components/search/_/index.ts", "src/templates/assets/javascripts/components/search/highlight/index.ts", "src/templates/assets/javascripts/components/sidebar/index.ts", "src/templates/assets/javascripts/components/source/facts/github/index.ts", "src/templates/assets/javascripts/components/source/facts/gitlab/index.ts", "src/templates/assets/javascripts/components/source/facts/_/index.ts", "src/templates/assets/javascripts/components/source/_/index.ts", "src/templates/assets/javascripts/components/tabs/index.ts", "src/templates/assets/javascripts/components/toc/index.ts", "src/templates/assets/javascripts/components/top/index.ts", "src/templates/assets/javascripts/patches/ellipsis/index.ts", "src/templates/assets/javascripts/patches/indeterminate/index.ts", "src/templates/assets/javascripts/patches/scrollfix/index.ts", "src/templates/assets/javascripts/patches/scrolllock/index.ts", "src/templates/assets/javascripts/polyfills/index.ts"], + "sourcesContent": ["(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (factory());\n}(this, (function () { 'use strict';\n\n /**\n * Applies the :focus-visible polyfill at the given scope.\n * A scope in this case is either the top-level Document or a Shadow Root.\n *\n * @param {(Document|ShadowRoot)} scope\n * @see https://github.com/WICG/focus-visible\n */\n function applyFocusVisiblePolyfill(scope) {\n var hadKeyboardEvent = true;\n var hadFocusVisibleRecently = false;\n var hadFocusVisibleRecentlyTimeout = null;\n\n var inputTypesAllowlist = {\n text: true,\n search: true,\n url: true,\n tel: true,\n email: true,\n password: true,\n number: true,\n date: true,\n month: true,\n week: true,\n time: true,\n datetime: true,\n 'datetime-local': true\n };\n\n /**\n * Helper function for legacy browsers and iframes which sometimes focus\n * elements like document, body, and non-interactive SVG.\n * @param {Element} el\n */\n function isValidFocusTarget(el) {\n if (\n el &&\n el !== document &&\n el.nodeName !== 'HTML' &&\n el.nodeName !== 'BODY' &&\n 'classList' in el &&\n 'contains' in el.classList\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * Computes whether the given element should automatically trigger the\n * `focus-visible` class being added, i.e. whether it should always match\n * `:focus-visible` when focused.\n * @param {Element} el\n * @return {boolean}\n */\n function focusTriggersKeyboardModality(el) {\n var type = el.type;\n var tagName = el.tagName;\n\n if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) {\n return true;\n }\n\n if (tagName === 'TEXTAREA' && !el.readOnly) {\n return true;\n }\n\n if (el.isContentEditable) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Add the `focus-visible` class to the given element if it was not added by\n * the author.\n * @param {Element} el\n */\n function addFocusVisibleClass(el) {\n if (el.classList.contains('focus-visible')) {\n return;\n }\n el.classList.add('focus-visible');\n el.setAttribute('data-focus-visible-added', '');\n }\n\n /**\n * Remove the `focus-visible` class from the given element if it was not\n * originally added by the author.\n * @param {Element} el\n */\n function removeFocusVisibleClass(el) {\n if (!el.hasAttribute('data-focus-visible-added')) {\n return;\n }\n el.classList.remove('focus-visible');\n el.removeAttribute('data-focus-visible-added');\n }\n\n /**\n * If the most recent user interaction was via the keyboard;\n * and the key press did not include a meta, alt/option, or control key;\n * then the modality is keyboard. Otherwise, the modality is not keyboard.\n * Apply `focus-visible` to any current active element and keep track\n * of our keyboard modality state with `hadKeyboardEvent`.\n * @param {KeyboardEvent} e\n */\n function onKeyDown(e) {\n if (e.metaKey || e.altKey || e.ctrlKey) {\n return;\n }\n\n if (isValidFocusTarget(scope.activeElement)) {\n addFocusVisibleClass(scope.activeElement);\n }\n\n hadKeyboardEvent = true;\n }\n\n /**\n * If at any point a user clicks with a pointing device, ensure that we change\n * the modality away from keyboard.\n * This avoids the situation where a user presses a key on an already focused\n * element, and then clicks on a different element, focusing it with a\n * pointing device, while we still think we're in keyboard modality.\n * @param {Event} e\n */\n function onPointerDown(e) {\n hadKeyboardEvent = false;\n }\n\n /**\n * On `focus`, add the `focus-visible` class to the target if:\n * - the target received focus as a result of keyboard navigation, or\n * - the event target is an element that will likely require interaction\n * via the keyboard (e.g. a text box)\n * @param {Event} e\n */\n function onFocus(e) {\n // Prevent IE from focusing the document or HTML element.\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {\n addFocusVisibleClass(e.target);\n }\n }\n\n /**\n * On `blur`, remove the `focus-visible` class from the target.\n * @param {Event} e\n */\n function onBlur(e) {\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (\n e.target.classList.contains('focus-visible') ||\n e.target.hasAttribute('data-focus-visible-added')\n ) {\n // To detect a tab/window switch, we look for a blur event followed\n // rapidly by a visibility change.\n // If we don't see a visibility change within 100ms, it's probably a\n // regular focus change.\n hadFocusVisibleRecently = true;\n window.clearTimeout(hadFocusVisibleRecentlyTimeout);\n hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {\n hadFocusVisibleRecently = false;\n }, 100);\n removeFocusVisibleClass(e.target);\n }\n }\n\n /**\n * If the user changes tabs, keep track of whether or not the previously\n * focused element had .focus-visible.\n * @param {Event} e\n */\n function onVisibilityChange(e) {\n if (document.visibilityState === 'hidden') {\n // If the tab becomes active again, the browser will handle calling focus\n // on the element (Safari actually calls it twice).\n // If this tab change caused a blur on an element with focus-visible,\n // re-apply the class when the user switches back to the tab.\n if (hadFocusVisibleRecently) {\n hadKeyboardEvent = true;\n }\n addInitialPointerMoveListeners();\n }\n }\n\n /**\n * Add a group of listeners to detect usage of any pointing devices.\n * These listeners will be added when the polyfill first loads, and anytime\n * the window is blurred, so that they are active when the window regains\n * focus.\n */\n function addInitialPointerMoveListeners() {\n document.addEventListener('mousemove', onInitialPointerMove);\n document.addEventListener('mousedown', onInitialPointerMove);\n document.addEventListener('mouseup', onInitialPointerMove);\n document.addEventListener('pointermove', onInitialPointerMove);\n document.addEventListener('pointerdown', onInitialPointerMove);\n document.addEventListener('pointerup', onInitialPointerMove);\n document.addEventListener('touchmove', onInitialPointerMove);\n document.addEventListener('touchstart', onInitialPointerMove);\n document.addEventListener('touchend', onInitialPointerMove);\n }\n\n function removeInitialPointerMoveListeners() {\n document.removeEventListener('mousemove', onInitialPointerMove);\n document.removeEventListener('mousedown', onInitialPointerMove);\n document.removeEventListener('mouseup', onInitialPointerMove);\n document.removeEventListener('pointermove', onInitialPointerMove);\n document.removeEventListener('pointerdown', onInitialPointerMove);\n document.removeEventListener('pointerup', onInitialPointerMove);\n document.removeEventListener('touchmove', onInitialPointerMove);\n document.removeEventListener('touchstart', onInitialPointerMove);\n document.removeEventListener('touchend', onInitialPointerMove);\n }\n\n /**\n * When the polfyill first loads, assume the user is in keyboard modality.\n * If any event is received from a pointing device (e.g. mouse, pointer,\n * touch), turn off keyboard modality.\n * This accounts for situations where focus enters the page from the URL bar.\n * @param {Event} e\n */\n function onInitialPointerMove(e) {\n // Work around a Safari quirk that fires a mousemove on whenever the\n // window blurs, even if you're tabbing out of the page. \u00AF\\_(\u30C4)_/\u00AF\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n document.documentElement.setAttribute('data-js-focus-visible', '');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n", "/*!\n * clipboard.js v2.0.11\n * https://clipboardjs.com/\n *\n * Licensed MIT \u00A9 Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function() { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 686:\n/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n \"default\": function() { return /* binding */ clipboard; }\n});\n\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(279);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(370);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(817);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n;// CONCATENATED MODULE: ./src/common/command.js\n/**\n * Executes a given operation type.\n * @param {String} type\n * @return {Boolean}\n */\nfunction command(type) {\n try {\n return document.execCommand(type);\n } catch (err) {\n return false;\n }\n}\n;// CONCATENATED MODULE: ./src/actions/cut.js\n\n\n/**\n * Cut action wrapper.\n * @param {String|HTMLElement} target\n * @return {String}\n */\n\nvar ClipboardActionCut = function ClipboardActionCut(target) {\n var selectedText = select_default()(target);\n command('cut');\n return selectedText;\n};\n\n/* harmony default export */ var actions_cut = (ClipboardActionCut);\n;// CONCATENATED MODULE: ./src/common/create-fake-element.js\n/**\n * Creates a fake textarea element with a value.\n * @param {String} value\n * @return {HTMLElement}\n */\nfunction createFakeElement(value) {\n var isRTL = document.documentElement.getAttribute('dir') === 'rtl';\n var fakeElement = document.createElement('textarea'); // Prevent zooming on iOS\n\n fakeElement.style.fontSize = '12pt'; // Reset box model\n\n fakeElement.style.border = '0';\n fakeElement.style.padding = '0';\n fakeElement.style.margin = '0'; // Move element out of screen horizontally\n\n fakeElement.style.position = 'absolute';\n fakeElement.style[isRTL ? 'right' : 'left'] = '-9999px'; // Move element to the same position vertically\n\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n fakeElement.style.top = \"\".concat(yPosition, \"px\");\n fakeElement.setAttribute('readonly', '');\n fakeElement.value = value;\n return fakeElement;\n}\n;// CONCATENATED MODULE: ./src/actions/copy.js\n\n\n\n/**\n * Create fake copy action wrapper using a fake element.\n * @param {String} target\n * @param {Object} options\n * @return {String}\n */\n\nvar fakeCopyAction = function fakeCopyAction(value, options) {\n var fakeElement = createFakeElement(value);\n options.container.appendChild(fakeElement);\n var selectedText = select_default()(fakeElement);\n command('copy');\n fakeElement.remove();\n return selectedText;\n};\n/**\n * Copy action wrapper.\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @return {String}\n */\n\n\nvar ClipboardActionCopy = function ClipboardActionCopy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n var selectedText = '';\n\n if (typeof target === 'string') {\n selectedText = fakeCopyAction(target, options);\n } else if (target instanceof HTMLInputElement && !['text', 'search', 'url', 'tel', 'password'].includes(target === null || target === void 0 ? void 0 : target.type)) {\n // If input type doesn't support `setSelectionRange`. Simulate it. https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange\n selectedText = fakeCopyAction(target.value, options);\n } else {\n selectedText = select_default()(target);\n command('copy');\n }\n\n return selectedText;\n};\n\n/* harmony default export */ var actions_copy = (ClipboardActionCopy);\n;// CONCATENATED MODULE: ./src/actions/default.js\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n\n\n/**\n * Inner function which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n * @param {Object} options\n */\n\nvar ClipboardActionDefault = function ClipboardActionDefault() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Defines base properties passed from constructor.\n var _options$action = options.action,\n action = _options$action === void 0 ? 'copy' : _options$action,\n container = options.container,\n target = options.target,\n text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'.\n\n if (action !== 'copy' && action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n } // Sets the `target` property using an element that will be have its content copied.\n\n\n if (target !== undefined) {\n if (target && _typeof(target) === 'object' && target.nodeType === 1) {\n if (action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n } // Define selection strategy based on `text` property.\n\n\n if (text) {\n return actions_copy(text, {\n container: container\n });\n } // Defines which selection strategy based on `target` property.\n\n\n if (target) {\n return action === 'cut' ? actions_cut(target) : actions_copy(target, {\n container: container\n });\n }\n};\n\n/* harmony default export */ var actions_default = (ClipboardActionDefault);\n;// CONCATENATED MODULE: ./src/clipboard.js\nfunction clipboard_typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return clipboard_typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (clipboard_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\n\n\n\n\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\nfunction getAttributeValue(suffix, element) {\n var attribute = \"data-clipboard-\".concat(suffix);\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\n\nvar Clipboard = /*#__PURE__*/function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n var _super = _createSuper(Clipboard);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n var _this;\n\n _classCallCheck(this, Clipboard);\n\n _this = _super.call(this);\n\n _this.resolveOptions(options);\n\n _this.listenClick(trigger);\n\n return _this;\n }\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n _createClass(Clipboard, [{\n key: \"resolveOptions\",\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: \"listenClick\",\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: \"onClick\",\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n var action = this.action(trigger) || 'copy';\n var text = actions_default({\n action: action,\n container: this.container,\n target: this.target(trigger),\n text: this.text(trigger)\n }); // Fires an event based on the copy operation result.\n\n this.emit(text ? 'success' : 'error', {\n action: action,\n text: text,\n trigger: trigger,\n clearSelection: function clearSelection() {\n if (trigger) {\n trigger.focus();\n }\n\n window.getSelection().removeAllRanges();\n }\n });\n }\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultAction\",\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: \"defaultTarget\",\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n /**\n * Allow fire programmatically a copy action\n * @param {String|HTMLElement} target\n * @param {Object} options\n * @returns Text copied.\n */\n\n }, {\n key: \"defaultText\",\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: \"destroy\",\n value: function destroy() {\n this.listener.destroy();\n }\n }], [{\n key: \"copy\",\n value: function copy(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n container: document.body\n };\n return actions_copy(target, options);\n }\n /**\n * Allow fire programmatically a cut action\n * @param {String|HTMLElement} target\n * @returns Text cutted.\n */\n\n }, {\n key: \"cut\",\n value: function cut(target) {\n return actions_cut(target);\n }\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: \"isSupported\",\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n return support;\n }\n }]);\n\n return Clipboard;\n}((tiny_emitter_default()));\n\n/* harmony default export */ var clipboard = (Clipboard);\n\n/***/ }),\n\n/***/ 828:\n/***/ (function(module) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n\n/***/ 438:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar closest = __webpack_require__(828);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n\n/***/ 879:\n/***/ (function(__unused_webpack_module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n\n/***/ 370:\n/***/ (function(module, __unused_webpack_exports, __webpack_require__) {\n\nvar is = __webpack_require__(879);\nvar delegate = __webpack_require__(438);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n\n/***/ 817:\n/***/ (function(module) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n\n/***/ 279:\n/***/ (function(module) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(__webpack_module_cache__[moduleId]) {\n/******/ \t\t\treturn __webpack_module_cache__[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\t// no module.id needed\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/compat get default export */\n/******/ \t!function() {\n/******/ \t\t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t\t__webpack_require__.n = function(module) {\n/******/ \t\t\tvar getter = module && module.__esModule ?\n/******/ \t\t\t\tfunction() { return module['default']; } :\n/******/ \t\t\t\tfunction() { return module; };\n/******/ \t\t\t__webpack_require__.d(getter, { a: getter });\n/******/ \t\t\treturn getter;\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/define property getters */\n/******/ \t!function() {\n/******/ \t\t// define getter functions for harmony exports\n/******/ \t\t__webpack_require__.d = function(exports, definition) {\n/******/ \t\t\tfor(var key in definition) {\n/******/ \t\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t\t}\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t}();\n/******/ \t\n/******/ \t/* webpack/runtime/hasOwnProperty shorthand */\n/******/ \t!function() {\n/******/ \t\t__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }\n/******/ \t}();\n/******/ \t\n/************************************************************************/\n/******/ \t// module exports must be returned from runtime so entry inlining is disabled\n/******/ \t// startup\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(686);\n/******/ })()\n.default;\n});", "/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n", "/*\n * Copyright (c) 2016-2024 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"focus-visible\"\n\nimport {\n EMPTY,\n NEVER,\n Observable,\n Subject,\n defer,\n delay,\n filter,\n map,\n merge,\n mergeWith,\n shareReplay,\n switchMap\n} from \"rxjs\"\n\nimport { configuration, feature } from \"./_\"\nimport {\n at,\n getActiveElement,\n getOptionalElement,\n requestJSON,\n setLocation,\n setToggle,\n watchDocument,\n watchKeyboard,\n watchLocation,\n watchLocationTarget,\n watchMedia,\n watchPrint,\n watchScript,\n watchViewport\n} from \"./browser\"\nimport {\n getComponentElement,\n getComponentElements,\n mountAnnounce,\n mountBackToTop,\n mountConsent,\n mountContent,\n mountDialog,\n mountHeader,\n mountHeaderTitle,\n mountPalette,\n mountProgress,\n mountSearch,\n mountSearchHiglight,\n mountSidebar,\n mountSource,\n mountTableOfContents,\n mountTabs,\n watchHeader,\n watchMain\n} from \"./components\"\nimport {\n SearchIndex,\n setupClipboardJS,\n setupInstantNavigation,\n setupVersionSelector\n} from \"./integrations\"\nimport {\n patchEllipsis,\n patchIndeterminate,\n patchScrollfix,\n patchScrolllock\n} from \"./patches\"\nimport \"./polyfills\"\n\n/* ----------------------------------------------------------------------------\n * Functions - @todo refactor\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch search index\n *\n * @returns Search index observable\n */\nfunction fetchSearchIndex(): Observable {\n if (location.protocol === \"file:\") {\n return watchScript(\n `${new URL(\"search/search_index.js\", config.base)}`\n )\n .pipe(\n // @ts-ignore - @todo fix typings\n map(() => __index),\n shareReplay(1)\n )\n } else {\n return requestJSON(\n new URL(\"search/search_index.json\", config.base)\n )\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Application\n * ------------------------------------------------------------------------- */\n\n/* Yay, JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Set up navigation observables and subjects */\nconst document$ = watchDocument()\nconst location$ = watchLocation()\nconst target$ = watchLocationTarget(location$)\nconst keyboard$ = watchKeyboard()\n\n/* Set up media observables */\nconst viewport$ = watchViewport()\nconst tablet$ = watchMedia(\"(min-width: 960px)\")\nconst screen$ = watchMedia(\"(min-width: 1220px)\")\nconst print$ = watchPrint()\n\n/* Retrieve search index, if search is enabled */\nconst config = configuration()\nconst index$ = document.forms.namedItem(\"search\")\n ? fetchSearchIndex()\n : NEVER\n\n/* Set up Clipboard.js integration */\nconst alert$ = new Subject()\nsetupClipboardJS({ alert$ })\n\n/* Set up progress indicator */\nconst progress$ = new Subject()\n\n/* Set up instant navigation, if enabled */\nif (feature(\"navigation.instant\"))\n setupInstantNavigation({ location$, viewport$, progress$ })\n .subscribe(document$)\n\n/* Set up version selector */\nif (config.version?.provider === \"mike\")\n setupVersionSelector({ document$ })\n\n/* Always close drawer and search on navigation */\nmerge(location$, target$)\n .pipe(\n delay(125)\n )\n .subscribe(() => {\n setToggle(\"drawer\", false)\n setToggle(\"search\", false)\n })\n\n/* Set up global keyboard handlers */\nkeyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\")\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Go to previous page */\n case \"p\":\n case \",\":\n const prev = getOptionalElement(\"link[rel=prev]\")\n if (typeof prev !== \"undefined\")\n setLocation(prev)\n break\n\n /* Go to next page */\n case \"n\":\n case \".\":\n const next = getOptionalElement(\"link[rel=next]\")\n if (typeof next !== \"undefined\")\n setLocation(next)\n break\n\n /* Expand navigation, see https://bit.ly/3ZjG5io */\n case \"Enter\":\n const active = getActiveElement()\n if (active instanceof HTMLLabelElement)\n active.click()\n }\n })\n\n/* Set up patches */\npatchEllipsis({ viewport$, document$ })\npatchIndeterminate({ document$, tablet$ })\npatchScrollfix({ document$ })\npatchScrolllock({ viewport$, tablet$ })\n\n/* Set up header and main area observable */\nconst header$ = watchHeader(getComponentElement(\"header\"), { viewport$ })\nconst main$ = document$\n .pipe(\n map(() => getComponentElement(\"main\")),\n switchMap(el => watchMain(el, { viewport$, header$ })),\n shareReplay(1)\n )\n\n/* Set up control component observables */\nconst control$ = merge(\n\n /* Consent */\n ...getComponentElements(\"consent\")\n .map(el => mountConsent(el, { target$ })),\n\n /* Dialog */\n ...getComponentElements(\"dialog\")\n .map(el => mountDialog(el, { alert$ })),\n\n /* Header */\n ...getComponentElements(\"header\")\n .map(el => mountHeader(el, { viewport$, header$, main$ })),\n\n /* Color palette */\n ...getComponentElements(\"palette\")\n .map(el => mountPalette(el)),\n\n /* Progress bar */\n ...getComponentElements(\"progress\")\n .map(el => mountProgress(el, { progress$ })),\n\n /* Search */\n ...getComponentElements(\"search\")\n .map(el => mountSearch(el, { index$, keyboard$ })),\n\n /* Repository information */\n ...getComponentElements(\"source\")\n .map(el => mountSource(el))\n)\n\n/* Set up content component observables */\nconst content$ = defer(() => merge(\n\n /* Announcement bar */\n ...getComponentElements(\"announce\")\n .map(el => mountAnnounce(el)),\n\n /* Content */\n ...getComponentElements(\"content\")\n .map(el => mountContent(el, { viewport$, target$, print$ })),\n\n /* Search highlighting */\n ...getComponentElements(\"content\")\n .map(el => feature(\"search.highlight\")\n ? mountSearchHiglight(el, { index$, location$ })\n : EMPTY\n ),\n\n /* Header title */\n ...getComponentElements(\"header-title\")\n .map(el => mountHeaderTitle(el, { viewport$, header$ })),\n\n /* Sidebar */\n ...getComponentElements(\"sidebar\")\n .map(el => el.getAttribute(\"data-md-type\") === \"navigation\"\n ? at(screen$, () => mountSidebar(el, { viewport$, header$, main$ }))\n : at(tablet$, () => mountSidebar(el, { viewport$, header$, main$ }))\n ),\n\n /* Navigation tabs */\n ...getComponentElements(\"tabs\")\n .map(el => mountTabs(el, { viewport$, header$ })),\n\n /* Table of contents */\n ...getComponentElements(\"toc\")\n .map(el => mountTableOfContents(el, {\n viewport$, header$, main$, target$\n })),\n\n /* Back-to-top button */\n ...getComponentElements(\"top\")\n .map(el => mountBackToTop(el, { viewport$, header$, main$, target$ }))\n))\n\n/* Set up component observables */\nconst component$ = document$\n .pipe(\n switchMap(() => content$),\n mergeWith(control$),\n shareReplay(1)\n )\n\n/* Subscribe to all components */\ncomponent$.subscribe()\n\n/* ----------------------------------------------------------------------------\n * Exports\n * ------------------------------------------------------------------------- */\n\nwindow.document$ = document$ /* Document observable */\nwindow.location$ = location$ /* Location subject */\nwindow.target$ = target$ /* Location target observable */\nwindow.keyboard$ = keyboard$ /* Keyboard observable */\nwindow.viewport$ = viewport$ /* Viewport observable */\nwindow.tablet$ = tablet$ /* Media tablet observable */\nwindow.screen$ = screen$ /* Media screen observable */\nwindow.print$ = print$ /* Media print observable */\nwindow.alert$ = alert$ /* Alert subject */\nwindow.progress$ = progress$ /* Progress indicator subject */\nwindow.component$ = component$ /* Component observable */\n", "/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n", "/**\n * Returns true if the object is a function.\n * @param value The value to check\n */\nexport function isFunction(value: any): value is (...args: any[]) => any {\n return typeof value === 'function';\n}\n", "/**\n * Used to create Error subclasses until the community moves away from ES5.\n *\n * This is because compiling from TypeScript down to ES5 has issues with subclassing Errors\n * as well as other built-in types: https://github.com/Microsoft/TypeScript/issues/12123\n *\n * @param createImpl A factory function to create the actual constructor implementation. The returned\n * function should be a named function that calls `_super` internally.\n */\nexport function createErrorClass(createImpl: (_super: any) => any): T {\n const _super = (instance: any) => {\n Error.call(instance);\n instance.stack = new Error().stack;\n };\n\n const ctorFunc = createImpl(_super);\n ctorFunc.prototype = Object.create(Error.prototype);\n ctorFunc.prototype.constructor = ctorFunc;\n return ctorFunc;\n}\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface UnsubscriptionError extends Error {\n readonly errors: any[];\n}\n\nexport interface UnsubscriptionErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (errors: any[]): UnsubscriptionError;\n}\n\n/**\n * An error thrown when one or more errors have occurred during the\n * `unsubscribe` of a {@link Subscription}.\n */\nexport const UnsubscriptionError: UnsubscriptionErrorCtor = createErrorClass(\n (_super) =>\n function UnsubscriptionErrorImpl(this: any, errors: (Error | string)[]) {\n _super(this);\n this.message = errors\n ? `${errors.length} errors occurred during unsubscription:\n${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\\n ')}`\n : '';\n this.name = 'UnsubscriptionError';\n this.errors = errors;\n }\n);\n", "/**\n * Removes an item from an array, mutating it.\n * @param arr The array to remove the item from\n * @param item The item to remove\n */\nexport function arrRemove(arr: T[] | undefined | null, item: T) {\n if (arr) {\n const index = arr.indexOf(item);\n 0 <= index && arr.splice(index, 1);\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { UnsubscriptionError } from './util/UnsubscriptionError';\nimport { SubscriptionLike, TeardownLogic, Unsubscribable } from './types';\nimport { arrRemove } from './util/arrRemove';\n\n/**\n * Represents a disposable resource, such as the execution of an Observable. A\n * Subscription has one important method, `unsubscribe`, that takes no argument\n * and just disposes the resource held by the subscription.\n *\n * Additionally, subscriptions may be grouped together through the `add()`\n * method, which will attach a child Subscription to the current Subscription.\n * When a Subscription is unsubscribed, all its children (and its grandchildren)\n * will be unsubscribed as well.\n *\n * @class Subscription\n */\nexport class Subscription implements SubscriptionLike {\n /** @nocollapse */\n public static EMPTY = (() => {\n const empty = new Subscription();\n empty.closed = true;\n return empty;\n })();\n\n /**\n * A flag to indicate whether this Subscription has already been unsubscribed.\n */\n public closed = false;\n\n private _parentage: Subscription[] | Subscription | null = null;\n\n /**\n * The list of registered finalizers to execute upon unsubscription. Adding and removing from this\n * list occurs in the {@link #add} and {@link #remove} methods.\n */\n private _finalizers: Exclude[] | null = null;\n\n /**\n * @param initialTeardown A function executed first as part of the finalization\n * process that is kicked off when {@link #unsubscribe} is called.\n */\n constructor(private initialTeardown?: () => void) {}\n\n /**\n * Disposes the resources held by the subscription. May, for instance, cancel\n * an ongoing Observable execution or cancel any other type of work that\n * started when the Subscription was created.\n * @return {void}\n */\n unsubscribe(): void {\n let errors: any[] | undefined;\n\n if (!this.closed) {\n this.closed = true;\n\n // Remove this from it's parents.\n const { _parentage } = this;\n if (_parentage) {\n this._parentage = null;\n if (Array.isArray(_parentage)) {\n for (const parent of _parentage) {\n parent.remove(this);\n }\n } else {\n _parentage.remove(this);\n }\n }\n\n const { initialTeardown: initialFinalizer } = this;\n if (isFunction(initialFinalizer)) {\n try {\n initialFinalizer();\n } catch (e) {\n errors = e instanceof UnsubscriptionError ? e.errors : [e];\n }\n }\n\n const { _finalizers } = this;\n if (_finalizers) {\n this._finalizers = null;\n for (const finalizer of _finalizers) {\n try {\n execFinalizer(finalizer);\n } catch (err) {\n errors = errors ?? [];\n if (err instanceof UnsubscriptionError) {\n errors = [...errors, ...err.errors];\n } else {\n errors.push(err);\n }\n }\n }\n }\n\n if (errors) {\n throw new UnsubscriptionError(errors);\n }\n }\n }\n\n /**\n * Adds a finalizer to this subscription, so that finalization will be unsubscribed/called\n * when this subscription is unsubscribed. If this subscription is already {@link #closed},\n * because it has already been unsubscribed, then whatever finalizer is passed to it\n * will automatically be executed (unless the finalizer itself is also a closed subscription).\n *\n * Closed Subscriptions cannot be added as finalizers to any subscription. Adding a closed\n * subscription to a any subscription will result in no operation. (A noop).\n *\n * Adding a subscription to itself, or adding `null` or `undefined` will not perform any\n * operation at all. (A noop).\n *\n * `Subscription` instances that are added to this instance will automatically remove themselves\n * if they are unsubscribed. Functions and {@link Unsubscribable} objects that you wish to remove\n * will need to be removed manually with {@link #remove}\n *\n * @param teardown The finalization logic to add to this subscription.\n */\n add(teardown: TeardownLogic): void {\n // Only add the finalizer if it's not undefined\n // and don't add a subscription to itself.\n if (teardown && teardown !== this) {\n if (this.closed) {\n // If this subscription is already closed,\n // execute whatever finalizer is handed to it automatically.\n execFinalizer(teardown);\n } else {\n if (teardown instanceof Subscription) {\n // We don't add closed subscriptions, and we don't add the same subscription\n // twice. Subscription unsubscribe is idempotent.\n if (teardown.closed || teardown._hasParent(this)) {\n return;\n }\n teardown._addParent(this);\n }\n (this._finalizers = this._finalizers ?? []).push(teardown);\n }\n }\n }\n\n /**\n * Checks to see if a this subscription already has a particular parent.\n * This will signal that this subscription has already been added to the parent in question.\n * @param parent the parent to check for\n */\n private _hasParent(parent: Subscription) {\n const { _parentage } = this;\n return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));\n }\n\n /**\n * Adds a parent to this subscription so it can be removed from the parent if it\n * unsubscribes on it's own.\n *\n * NOTE: THIS ASSUMES THAT {@link _hasParent} HAS ALREADY BEEN CHECKED.\n * @param parent The parent subscription to add\n */\n private _addParent(parent: Subscription) {\n const { _parentage } = this;\n this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;\n }\n\n /**\n * Called on a child when it is removed via {@link #remove}.\n * @param parent The parent to remove\n */\n private _removeParent(parent: Subscription) {\n const { _parentage } = this;\n if (_parentage === parent) {\n this._parentage = null;\n } else if (Array.isArray(_parentage)) {\n arrRemove(_parentage, parent);\n }\n }\n\n /**\n * Removes a finalizer from this subscription that was previously added with the {@link #add} method.\n *\n * Note that `Subscription` instances, when unsubscribed, will automatically remove themselves\n * from every other `Subscription` they have been added to. This means that using the `remove` method\n * is not a common thing and should be used thoughtfully.\n *\n * If you add the same finalizer instance of a function or an unsubscribable object to a `Subscription` instance\n * more than once, you will need to call `remove` the same number of times to remove all instances.\n *\n * All finalizer instances are removed to free up memory upon unsubscription.\n *\n * @param teardown The finalizer to remove from this subscription\n */\n remove(teardown: Exclude): void {\n const { _finalizers } = this;\n _finalizers && arrRemove(_finalizers, teardown);\n\n if (teardown instanceof Subscription) {\n teardown._removeParent(this);\n }\n }\n}\n\nexport const EMPTY_SUBSCRIPTION = Subscription.EMPTY;\n\nexport function isSubscription(value: any): value is Subscription {\n return (\n value instanceof Subscription ||\n (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe))\n );\n}\n\nfunction execFinalizer(finalizer: Unsubscribable | (() => void)) {\n if (isFunction(finalizer)) {\n finalizer();\n } else {\n finalizer.unsubscribe();\n }\n}\n", "import { Subscriber } from './Subscriber';\nimport { ObservableNotification } from './types';\n\n/**\n * The {@link GlobalConfig} object for RxJS. It is used to configure things\n * like how to react on unhandled errors.\n */\nexport const config: GlobalConfig = {\n onUnhandledError: null,\n onStoppedNotification: null,\n Promise: undefined,\n useDeprecatedSynchronousErrorHandling: false,\n useDeprecatedNextContext: false,\n};\n\n/**\n * The global configuration object for RxJS, used to configure things\n * like how to react on unhandled errors. Accessible via {@link config}\n * object.\n */\nexport interface GlobalConfig {\n /**\n * A registration point for unhandled errors from RxJS. These are errors that\n * cannot were not handled by consuming code in the usual subscription path. For\n * example, if you have this configured, and you subscribe to an observable without\n * providing an error handler, errors from that subscription will end up here. This\n * will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onUnhandledError: ((err: any) => void) | null;\n\n /**\n * A registration point for notifications that cannot be sent to subscribers because they\n * have completed, errored or have been explicitly unsubscribed. By default, next, complete\n * and error notifications sent to stopped subscribers are noops. However, sometimes callers\n * might want a different behavior. For example, with sources that attempt to report errors\n * to stopped subscribers, a caller can configure RxJS to throw an unhandled error instead.\n * This will _always_ be called asynchronously on another job in the runtime. This is because\n * we do not want errors thrown in this user-configured handler to interfere with the\n * behavior of the library.\n */\n onStoppedNotification: ((notification: ObservableNotification, subscriber: Subscriber) => void) | null;\n\n /**\n * The promise constructor used by default for {@link Observable#toPromise toPromise} and {@link Observable#forEach forEach}\n * methods.\n *\n * @deprecated As of version 8, RxJS will no longer support this sort of injection of a\n * Promise constructor. If you need a Promise implementation other than native promises,\n * please polyfill/patch Promise as you see appropriate. Will be removed in v8.\n */\n Promise?: PromiseConstructorLike;\n\n /**\n * If true, turns on synchronous error rethrowing, which is a deprecated behavior\n * in v6 and higher. This behavior enables bad patterns like wrapping a subscribe\n * call in a try/catch block. It also enables producer interference, a nasty bug\n * where a multicast can be broken for all observers by a downstream consumer with\n * an unhandled error. DO NOT USE THIS FLAG UNLESS IT'S NEEDED TO BUY TIME\n * FOR MIGRATION REASONS.\n *\n * @deprecated As of version 8, RxJS will no longer support synchronous throwing\n * of unhandled errors. All errors will be thrown on a separate call stack to prevent bad\n * behaviors described above. Will be removed in v8.\n */\n useDeprecatedSynchronousErrorHandling: boolean;\n\n /**\n * If true, enables an as-of-yet undocumented feature from v5: The ability to access\n * `unsubscribe()` via `this` context in `next` functions created in observers passed\n * to `subscribe`.\n *\n * This is being removed because the performance was severely problematic, and it could also cause\n * issues when types other than POJOs are passed to subscribe as subscribers, as they will likely have\n * their `this` context overwritten.\n *\n * @deprecated As of version 8, RxJS will no longer support altering the\n * context of next functions provided as part of an observer to Subscribe. Instead,\n * you will have access to a subscription or a signal or token that will allow you to do things like\n * unsubscribe and test closed status. Will be removed in v8.\n */\n useDeprecatedNextContext: boolean;\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetTimeoutFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearTimeoutFunction = (handle: TimerHandle) => void;\n\ninterface TimeoutProvider {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n delegate:\n | {\n setTimeout: SetTimeoutFunction;\n clearTimeout: ClearTimeoutFunction;\n }\n | undefined;\n}\n\nexport const timeoutProvider: TimeoutProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setTimeout(handler: () => void, timeout?: number, ...args) {\n const { delegate } = timeoutProvider;\n if (delegate?.setTimeout) {\n return delegate.setTimeout(handler, timeout, ...args);\n }\n return setTimeout(handler, timeout, ...args);\n },\n clearTimeout(handle) {\n const { delegate } = timeoutProvider;\n return (delegate?.clearTimeout || clearTimeout)(handle as any);\n },\n delegate: undefined,\n};\n", "import { config } from '../config';\nimport { timeoutProvider } from '../scheduler/timeoutProvider';\n\n/**\n * Handles an error on another job either with the user-configured {@link onUnhandledError},\n * or by throwing it on that new job so it can be picked up by `window.onerror`, `process.on('error')`, etc.\n *\n * This should be called whenever there is an error that is out-of-band with the subscription\n * or when an error hits a terminal boundary of the subscription and no error handler was provided.\n *\n * @param err the error to report\n */\nexport function reportUnhandledError(err: any) {\n timeoutProvider.setTimeout(() => {\n const { onUnhandledError } = config;\n if (onUnhandledError) {\n // Execute the user-configured error handler.\n onUnhandledError(err);\n } else {\n // Throw so it is picked up by the runtime's uncaught error mechanism.\n throw err;\n }\n });\n}\n", "/* tslint:disable:no-empty */\nexport function noop() { }\n", "import { CompleteNotification, NextNotification, ErrorNotification } from './types';\n\n/**\n * A completion object optimized for memory use and created to be the\n * same \"shape\" as other notifications in v8.\n * @internal\n */\nexport const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined) as CompleteNotification)();\n\n/**\n * Internal use only. Creates an optimized error notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function errorNotification(error: any): ErrorNotification {\n return createNotification('E', undefined, error) as any;\n}\n\n/**\n * Internal use only. Creates an optimized next notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function nextNotification(value: T) {\n return createNotification('N', value, undefined) as NextNotification;\n}\n\n/**\n * Ensures that all notifications created internally have the same \"shape\" in v8.\n *\n * TODO: This is only exported to support a crazy legacy test in `groupBy`.\n * @internal\n */\nexport function createNotification(kind: 'N' | 'E' | 'C', value: any, error: any) {\n return {\n kind,\n value,\n error,\n };\n}\n", "import { config } from '../config';\n\nlet context: { errorThrown: boolean; error: any } | null = null;\n\n/**\n * Handles dealing with errors for super-gross mode. Creates a context, in which\n * any synchronously thrown errors will be passed to {@link captureError}. Which\n * will record the error such that it will be rethrown after the call back is complete.\n * TODO: Remove in v8\n * @param cb An immediately executed function.\n */\nexport function errorContext(cb: () => void) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n const isRoot = !context;\n if (isRoot) {\n context = { errorThrown: false, error: null };\n }\n cb();\n if (isRoot) {\n const { errorThrown, error } = context!;\n context = null;\n if (errorThrown) {\n throw error;\n }\n }\n } else {\n // This is the general non-deprecated path for everyone that\n // isn't crazy enough to use super-gross mode (useDeprecatedSynchronousErrorHandling)\n cb();\n }\n}\n\n/**\n * Captures errors only in super-gross mode.\n * @param err the error to capture\n */\nexport function captureError(err: any) {\n if (config.useDeprecatedSynchronousErrorHandling && context) {\n context.errorThrown = true;\n context.error = err;\n }\n}\n", "import { isFunction } from './util/isFunction';\nimport { Observer, ObservableNotification } from './types';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nimport { captureError } from './util/errorContext';\n\n/**\n * Implements the {@link Observer} interface and extends the\n * {@link Subscription} class. While the {@link Observer} is the public API for\n * consuming the values of an {@link Observable}, all Observers get converted to\n * a Subscriber, in order to provide Subscription-like capabilities such as\n * `unsubscribe`. Subscriber is a common type in RxJS, and crucial for\n * implementing operators, but it is rarely used as a public API.\n *\n * @class Subscriber\n */\nexport class Subscriber extends Subscription implements Observer {\n /**\n * A static factory for a Subscriber, given a (potentially partial) definition\n * of an Observer.\n * @param next The `next` callback of an Observer.\n * @param error The `error` callback of an\n * Observer.\n * @param complete The `complete` callback of an\n * Observer.\n * @return A Subscriber wrapping the (partially defined)\n * Observer represented by the given arguments.\n * @nocollapse\n * @deprecated Do not use. Will be removed in v8. There is no replacement for this\n * method, and there is no reason to be creating instances of `Subscriber` directly.\n * If you have a specific use case, please file an issue.\n */\n static create(next?: (x?: T) => void, error?: (e?: any) => void, complete?: () => void): Subscriber {\n return new SafeSubscriber(next, error, complete);\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected isStopped: boolean = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n protected destination: Subscriber | Observer; // this `any` is the escape hatch to erase extra type param (e.g. R)\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * There is no reason to directly create an instance of Subscriber. This type is exported for typings reasons.\n */\n constructor(destination?: Subscriber | Observer) {\n super();\n if (destination) {\n this.destination = destination;\n // Automatically chain subscriptions together here.\n // if destination is a Subscription, then it is a Subscriber.\n if (isSubscription(destination)) {\n destination.add(this);\n }\n } else {\n this.destination = EMPTY_OBSERVER;\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `next` from\n * the Observable, with a value. The Observable may call this method 0 or more\n * times.\n * @param {T} [value] The `next` value.\n * @return {void}\n */\n next(value?: T): void {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n } else {\n this._next(value!);\n }\n }\n\n /**\n * The {@link Observer} callback to receive notifications of type `error` from\n * the Observable, with an attached `Error`. Notifies the Observer that\n * the Observable has experienced an error condition.\n * @param {any} [err] The `error` exception.\n * @return {void}\n */\n error(err?: any): void {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n } else {\n this.isStopped = true;\n this._error(err);\n }\n }\n\n /**\n * The {@link Observer} callback to receive a valueless notification of type\n * `complete` from the Observable. Notifies the Observer that the Observable\n * has finished sending push-based notifications.\n * @return {void}\n */\n complete(): void {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n } else {\n this.isStopped = true;\n this._complete();\n }\n }\n\n unsubscribe(): void {\n if (!this.closed) {\n this.isStopped = true;\n super.unsubscribe();\n this.destination = null!;\n }\n }\n\n protected _next(value: T): void {\n this.destination.next(value);\n }\n\n protected _error(err: any): void {\n try {\n this.destination.error(err);\n } finally {\n this.unsubscribe();\n }\n }\n\n protected _complete(): void {\n try {\n this.destination.complete();\n } finally {\n this.unsubscribe();\n }\n }\n}\n\n/**\n * This bind is captured here because we want to be able to have\n * compatibility with monoid libraries that tend to use a method named\n * `bind`. In particular, a library called Monio requires this.\n */\nconst _bind = Function.prototype.bind;\n\nfunction bind any>(fn: Fn, thisArg: any): Fn {\n return _bind.call(fn, thisArg);\n}\n\n/**\n * Internal optimization only, DO NOT EXPOSE.\n * @internal\n */\nclass ConsumerObserver implements Observer {\n constructor(private partialObserver: Partial>) {}\n\n next(value: T): void {\n const { partialObserver } = this;\n if (partialObserver.next) {\n try {\n partialObserver.next(value);\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n\n error(err: any): void {\n const { partialObserver } = this;\n if (partialObserver.error) {\n try {\n partialObserver.error(err);\n } catch (error) {\n handleUnhandledError(error);\n }\n } else {\n handleUnhandledError(err);\n }\n }\n\n complete(): void {\n const { partialObserver } = this;\n if (partialObserver.complete) {\n try {\n partialObserver.complete();\n } catch (error) {\n handleUnhandledError(error);\n }\n }\n }\n}\n\nexport class SafeSubscriber extends Subscriber {\n constructor(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((e?: any) => void) | null,\n complete?: (() => void) | null\n ) {\n super();\n\n let partialObserver: Partial>;\n if (isFunction(observerOrNext) || !observerOrNext) {\n // The first argument is a function, not an observer. The next\n // two arguments *could* be observers, or they could be empty.\n partialObserver = {\n next: (observerOrNext ?? undefined) as (((value: T) => void) | undefined),\n error: error ?? undefined,\n complete: complete ?? undefined,\n };\n } else {\n // The first argument is a partial observer.\n let context: any;\n if (this && config.useDeprecatedNextContext) {\n // This is a deprecated path that made `this.unsubscribe()` available in\n // next handler functions passed to subscribe. This only exists behind a flag\n // now, as it is *very* slow.\n context = Object.create(observerOrNext);\n context.unsubscribe = () => this.unsubscribe();\n partialObserver = {\n next: observerOrNext.next && bind(observerOrNext.next, context),\n error: observerOrNext.error && bind(observerOrNext.error, context),\n complete: observerOrNext.complete && bind(observerOrNext.complete, context),\n };\n } else {\n // The \"normal\" path. Just use the partial observer directly.\n partialObserver = observerOrNext;\n }\n }\n\n // Wrap the partial observer to ensure it's a full observer, and\n // make sure proper error handling is accounted for.\n this.destination = new ConsumerObserver(partialObserver);\n }\n}\n\nfunction handleUnhandledError(error: any) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n captureError(error);\n } else {\n // Ideal path, we report this as an unhandled error,\n // which is thrown on a new call stack.\n reportUnhandledError(error);\n }\n}\n\n/**\n * An error handler used when no error handler was supplied\n * to the SafeSubscriber -- meaning no error handler was supplied\n * do the `subscribe` call on our observable.\n * @param err The error to handle\n */\nfunction defaultErrorHandler(err: any) {\n throw err;\n}\n\n/**\n * A handler for notifications that cannot be sent to a stopped subscriber.\n * @param notification The notification being sent\n * @param subscriber The stopped subscriber\n */\nfunction handleStoppedNotification(notification: ObservableNotification, subscriber: Subscriber) {\n const { onStoppedNotification } = config;\n onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));\n}\n\n/**\n * The observer used as a stub for subscriptions where the user did not\n * pass any arguments to `subscribe`. Comes with the default error handling\n * behavior.\n */\nexport const EMPTY_OBSERVER: Readonly> & { closed: true } = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop,\n};\n", "/**\n * Symbol.observable or a string \"@@observable\". Used for interop\n *\n * @deprecated We will no longer be exporting this symbol in upcoming versions of RxJS.\n * Instead polyfill and use Symbol.observable directly *or* use https://www.npmjs.com/package/symbol-observable\n */\nexport const observable: string | symbol = (() => (typeof Symbol === 'function' && Symbol.observable) || '@@observable')();\n", "/**\n * This function takes one parameter and just returns it. Simply put,\n * this is like `(x: T): T => x`.\n *\n * ## Examples\n *\n * This is useful in some cases when using things like `mergeMap`\n *\n * ```ts\n * import { interval, take, map, range, mergeMap, identity } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(5));\n *\n * const result$ = source$.pipe(\n * map(i => range(i)),\n * mergeMap(identity) // same as mergeMap(x => x)\n * );\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * Or when you want to selectively apply an operator\n *\n * ```ts\n * import { interval, take, identity } from 'rxjs';\n *\n * const shouldLimit = () => Math.random() < 0.5;\n *\n * const source$ = interval(1000);\n *\n * const result$ = source$.pipe(shouldLimit() ? take(5) : identity);\n *\n * result$.subscribe({\n * next: console.log\n * });\n * ```\n *\n * @param x Any value that is returned by this function\n * @returns The value passed as the first parameter to this function\n */\nexport function identity(x: T): T {\n return x;\n}\n", "import { identity } from './identity';\nimport { UnaryFunction } from '../types';\n\nexport function pipe(): typeof identity;\nexport function pipe(fn1: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction): UnaryFunction;\nexport function pipe(fn1: UnaryFunction, fn2: UnaryFunction, fn3: UnaryFunction): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction\n): UnaryFunction;\nexport function pipe(\n fn1: UnaryFunction,\n fn2: UnaryFunction,\n fn3: UnaryFunction,\n fn4: UnaryFunction,\n fn5: UnaryFunction,\n fn6: UnaryFunction,\n fn7: UnaryFunction,\n fn8: UnaryFunction,\n fn9: UnaryFunction,\n ...fns: UnaryFunction[]\n): UnaryFunction;\n\n/**\n * pipe() can be called on one or more functions, each of which can take one argument (\"UnaryFunction\")\n * and uses it to return a value.\n * It returns a function that takes one argument, passes it to the first UnaryFunction, and then\n * passes the result to the next one, passes that result to the next one, and so on. \n */\nexport function pipe(...fns: Array>): UnaryFunction {\n return pipeFromArray(fns);\n}\n\n/** @internal */\nexport function pipeFromArray(fns: Array>): UnaryFunction {\n if (fns.length === 0) {\n return identity as UnaryFunction;\n }\n\n if (fns.length === 1) {\n return fns[0];\n }\n\n return function piped(input: T): R {\n return fns.reduce((prev: any, fn: UnaryFunction) => fn(prev), input as any);\n };\n}\n", "import { Operator } from './Operator';\nimport { SafeSubscriber, Subscriber } from './Subscriber';\nimport { isSubscription, Subscription } from './Subscription';\nimport { TeardownLogic, OperatorFunction, Subscribable, Observer } from './types';\nimport { observable as Symbol_observable } from './symbol/observable';\nimport { pipeFromArray } from './util/pipe';\nimport { config } from './config';\nimport { isFunction } from './util/isFunction';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A representation of any set of values over any amount of time. This is the most basic building block\n * of RxJS.\n *\n * @class Observable\n */\nexport class Observable implements Subscribable {\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n source: Observable | undefined;\n\n /**\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\n operator: Operator | undefined;\n\n /**\n * @constructor\n * @param {Function} subscribe the function that is called when the Observable is\n * initially subscribed to. This function is given a Subscriber, to which new values\n * can be `next`ed, or an `error` method can be called to raise an error, or\n * `complete` can be called to notify of a successful completion.\n */\n constructor(subscribe?: (this: Observable, subscriber: Subscriber) => TeardownLogic) {\n if (subscribe) {\n this._subscribe = subscribe;\n }\n }\n\n // HACK: Since TypeScript inherits static properties too, we have to\n // fight against TypeScript here so Subject can have a different static create signature\n /**\n * Creates a new Observable by calling the Observable constructor\n * @owner Observable\n * @method create\n * @param {Function} subscribe? the subscriber function to be passed to the Observable constructor\n * @return {Observable} a new observable\n * @nocollapse\n * @deprecated Use `new Observable()` instead. Will be removed in v8.\n */\n static create: (...args: any[]) => any = (subscribe?: (subscriber: Subscriber) => TeardownLogic) => {\n return new Observable(subscribe);\n };\n\n /**\n * Creates a new Observable, with this Observable instance as the source, and the passed\n * operator defined as the new observable's operator.\n * @method lift\n * @param operator the operator defining the operation to take on the observable\n * @return a new observable with the Operator applied\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n * If you have implemented an operator using `lift`, it is recommended that you create an\n * operator by simply returning `new Observable()` directly. See \"Creating new operators from\n * scratch\" section here: https://rxjs.dev/guide/operators\n */\n lift(operator?: Operator): Observable {\n const observable = new Observable();\n observable.source = this;\n observable.operator = operator;\n return observable;\n }\n\n subscribe(observerOrNext?: Partial> | ((value: T) => void)): Subscription;\n /** @deprecated Instead of passing separate callback arguments, use an observer argument. Signatures taking separate callback arguments will be removed in v8. Details: https://rxjs.dev/deprecations/subscribe-arguments */\n subscribe(next?: ((value: T) => void) | null, error?: ((error: any) => void) | null, complete?: (() => void) | null): Subscription;\n /**\n * Invokes an execution of an Observable and registers Observer handlers for notifications it will emit.\n *\n * Use it when you have all these Observables, but still nothing is happening.\n *\n * `subscribe` is not a regular operator, but a method that calls Observable's internal `subscribe` function. It\n * might be for example a function that you passed to Observable's constructor, but most of the time it is\n * a library implementation, which defines what will be emitted by an Observable, and when it be will emitted. This means\n * that calling `subscribe` is actually the moment when Observable starts its work, not when it is created, as it is often\n * the thought.\n *\n * Apart from starting the execution of an Observable, this method allows you to listen for values\n * that an Observable emits, as well as for when it completes or errors. You can achieve this in two\n * of the following ways.\n *\n * The first way is creating an object that implements {@link Observer} interface. It should have methods\n * defined by that interface, but note that it should be just a regular JavaScript object, which you can create\n * yourself in any way you want (ES6 class, classic function constructor, object literal etc.). In particular, do\n * not attempt to use any RxJS implementation details to create Observers - you don't need them. Remember also\n * that your object does not have to implement all methods. If you find yourself creating a method that doesn't\n * do anything, you can simply omit it. Note however, if the `error` method is not provided and an error happens,\n * it will be thrown asynchronously. Errors thrown asynchronously cannot be caught using `try`/`catch`. Instead,\n * use the {@link onUnhandledError} configuration option or use a runtime handler (like `window.onerror` or\n * `process.on('error)`) to be notified of unhandled errors. Because of this, it's recommended that you provide\n * an `error` method to avoid missing thrown errors.\n *\n * The second way is to give up on Observer object altogether and simply provide callback functions in place of its methods.\n * This means you can provide three functions as arguments to `subscribe`, where the first function is equivalent\n * of a `next` method, the second of an `error` method and the third of a `complete` method. Just as in case of an Observer,\n * if you do not need to listen for something, you can omit a function by passing `undefined` or `null`,\n * since `subscribe` recognizes these functions by where they were placed in function call. When it comes\n * to the `error` function, as with an Observer, if not provided, errors emitted by an Observable will be thrown asynchronously.\n *\n * You can, however, subscribe with no parameters at all. This may be the case where you're not interested in terminal events\n * and you also handled emissions internally by using operators (e.g. using `tap`).\n *\n * Whichever style of calling `subscribe` you use, in both cases it returns a Subscription object.\n * This object allows you to call `unsubscribe` on it, which in turn will stop the work that an Observable does and will clean\n * up all resources that an Observable used. Note that cancelling a subscription will not call `complete` callback\n * provided to `subscribe` function, which is reserved for a regular completion signal that comes from an Observable.\n *\n * Remember that callbacks provided to `subscribe` are not guaranteed to be called asynchronously.\n * It is an Observable itself that decides when these functions will be called. For example {@link of}\n * by default emits all its values synchronously. Always check documentation for how given Observable\n * will behave when subscribed and if its default behavior can be modified with a `scheduler`.\n *\n * #### Examples\n *\n * Subscribe with an {@link guide/observer Observer}\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * const sumObserver = {\n * sum: 0,\n * next(value) {\n * console.log('Adding: ' + value);\n * this.sum = this.sum + value;\n * },\n * error() {\n * // We actually could just remove this method,\n * // since we do not really care about errors right now.\n * },\n * complete() {\n * console.log('Sum equals: ' + this.sum);\n * }\n * };\n *\n * of(1, 2, 3) // Synchronously emits 1, 2, 3 and then completes.\n * .subscribe(sumObserver);\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Subscribe with functions ({@link deprecations/subscribe-arguments deprecated})\n *\n * ```ts\n * import { of } from 'rxjs'\n *\n * let sum = 0;\n *\n * of(1, 2, 3).subscribe(\n * value => {\n * console.log('Adding: ' + value);\n * sum = sum + value;\n * },\n * undefined,\n * () => console.log('Sum equals: ' + sum)\n * );\n *\n * // Logs:\n * // 'Adding: 1'\n * // 'Adding: 2'\n * // 'Adding: 3'\n * // 'Sum equals: 6'\n * ```\n *\n * Cancel a subscription\n *\n * ```ts\n * import { interval } from 'rxjs';\n *\n * const subscription = interval(1000).subscribe({\n * next(num) {\n * console.log(num)\n * },\n * complete() {\n * // Will not be called, even when cancelling subscription.\n * console.log('completed!');\n * }\n * });\n *\n * setTimeout(() => {\n * subscription.unsubscribe();\n * console.log('unsubscribed!');\n * }, 2500);\n *\n * // Logs:\n * // 0 after 1s\n * // 1 after 2s\n * // 'unsubscribed!' after 2.5s\n * ```\n *\n * @param {Observer|Function} observerOrNext (optional) Either an observer with methods to be called,\n * or the first of three possible handlers, which is the handler for each value emitted from the subscribed\n * Observable.\n * @param {Function} error (optional) A handler for a terminal event resulting from an error. If no error handler is provided,\n * the error will be thrown asynchronously as unhandled.\n * @param {Function} complete (optional) A handler for a terminal event resulting from successful completion.\n * @return {Subscription} a subscription reference to the registered handlers\n * @method subscribe\n */\n subscribe(\n observerOrNext?: Partial> | ((value: T) => void) | null,\n error?: ((error: any) => void) | null,\n complete?: (() => void) | null\n ): Subscription {\n const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);\n\n errorContext(() => {\n const { operator, source } = this;\n subscriber.add(\n operator\n ? // We're dealing with a subscription in the\n // operator chain to one of our lifted operators.\n operator.call(subscriber, source)\n : source\n ? // If `source` has a value, but `operator` does not, something that\n // had intimate knowledge of our API, like our `Subject`, must have\n // set it. We're going to just call `_subscribe` directly.\n this._subscribe(subscriber)\n : // In all other cases, we're likely wrapping a user-provided initializer\n // function, so we need to catch errors and handle them appropriately.\n this._trySubscribe(subscriber)\n );\n });\n\n return subscriber;\n }\n\n /** @internal */\n protected _trySubscribe(sink: Subscriber): TeardownLogic {\n try {\n return this._subscribe(sink);\n } catch (err) {\n // We don't need to return anything in this case,\n // because it's just going to try to `add()` to a subscription\n // above.\n sink.error(err);\n }\n }\n\n /**\n * Used as a NON-CANCELLABLE means of subscribing to an observable, for use with\n * APIs that expect promises, like `async/await`. You cannot unsubscribe from this.\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * #### Example\n *\n * ```ts\n * import { interval, take } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(4));\n *\n * async function getTotal() {\n * let total = 0;\n *\n * await source$.forEach(value => {\n * total += value;\n * console.log('observable -> ' + value);\n * });\n *\n * return total;\n * }\n *\n * getTotal().then(\n * total => console.log('Total: ' + total)\n * );\n *\n * // Expected:\n * // 'observable -> 0'\n * // 'observable -> 1'\n * // 'observable -> 2'\n * // 'observable -> 3'\n * // 'Total: 6'\n * ```\n *\n * @param next a handler for each value emitted by the observable\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n */\n forEach(next: (value: T) => void): Promise;\n\n /**\n * @param next a handler for each value emitted by the observable\n * @param promiseCtor a constructor function used to instantiate the Promise\n * @return a promise that either resolves on observable completion or\n * rejects with the handled error\n * @deprecated Passing a Promise constructor will no longer be available\n * in upcoming versions of RxJS. This is because it adds weight to the library, for very\n * little benefit. If you need this functionality, it is recommended that you either\n * polyfill Promise, or you create an adapter to convert the returned native promise\n * to whatever promise implementation you wanted. Will be removed in v8.\n */\n forEach(next: (value: T) => void, promiseCtor: PromiseConstructorLike): Promise;\n\n forEach(next: (value: T) => void, promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n const subscriber = new SafeSubscriber({\n next: (value) => {\n try {\n next(value);\n } catch (err) {\n reject(err);\n subscriber.unsubscribe();\n }\n },\n error: reject,\n complete: resolve,\n });\n this.subscribe(subscriber);\n }) as Promise;\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): TeardownLogic {\n return this.source?.subscribe(subscriber);\n }\n\n /**\n * An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable\n * @method Symbol.observable\n * @return {Observable} this instance of the observable\n */\n [Symbol_observable]() {\n return this;\n }\n\n /* tslint:disable:max-line-length */\n pipe(): Observable;\n pipe(op1: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction): Observable;\n pipe(op1: OperatorFunction, op2: OperatorFunction, op3: OperatorFunction): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction\n ): Observable;\n pipe(\n op1: OperatorFunction,\n op2: OperatorFunction,\n op3: OperatorFunction,\n op4: OperatorFunction,\n op5: OperatorFunction,\n op6: OperatorFunction,\n op7: OperatorFunction,\n op8: OperatorFunction,\n op9: OperatorFunction,\n ...operations: OperatorFunction[]\n ): Observable;\n /* tslint:enable:max-line-length */\n\n /**\n * Used to stitch together functional operators into a chain.\n * @method pipe\n * @return {Observable} the Observable result of all of the operators having\n * been called in the order they were passed in.\n *\n * ## Example\n *\n * ```ts\n * import { interval, filter, map, scan } from 'rxjs';\n *\n * interval(1000)\n * .pipe(\n * filter(x => x % 2 === 0),\n * map(x => x + x),\n * scan((acc, x) => acc + x)\n * )\n * .subscribe(x => console.log(x));\n * ```\n */\n pipe(...operations: OperatorFunction[]): Observable {\n return pipeFromArray(operations)(this);\n }\n\n /* tslint:disable:max-line-length */\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: typeof Promise): Promise;\n /** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */\n toPromise(PromiseCtor: PromiseConstructorLike): Promise;\n /* tslint:enable:max-line-length */\n\n /**\n * Subscribe to this Observable and get a Promise resolving on\n * `complete` with the last emission (if any).\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * @method toPromise\n * @param [promiseCtor] a constructor function used to instantiate\n * the Promise\n * @return A Promise that resolves with the last value emit, or\n * rejects on an error. If there were no emissions, Promise\n * resolves with undefined.\n * @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise\n */\n toPromise(promiseCtor?: PromiseConstructorLike): Promise {\n promiseCtor = getPromiseCtor(promiseCtor);\n\n return new promiseCtor((resolve, reject) => {\n let value: T | undefined;\n this.subscribe(\n (x: T) => (value = x),\n (err: any) => reject(err),\n () => resolve(value)\n );\n }) as Promise;\n }\n}\n\n/**\n * Decides between a passed promise constructor from consuming code,\n * A default configured promise constructor, and the native promise\n * constructor and returns it. If nothing can be found, it will throw\n * an error.\n * @param promiseCtor The optional promise constructor to passed by consuming code\n */\nfunction getPromiseCtor(promiseCtor: PromiseConstructorLike | undefined) {\n return promiseCtor ?? config.Promise ?? Promise;\n}\n\nfunction isObserver(value: any): value is Observer {\n return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);\n}\n\nfunction isSubscriber(value: any): value is Subscriber {\n return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));\n}\n", "import { Observable } from '../Observable';\nimport { Subscriber } from '../Subscriber';\nimport { OperatorFunction } from '../types';\nimport { isFunction } from './isFunction';\n\n/**\n * Used to determine if an object is an Observable with a lift function.\n */\nexport function hasLift(source: any): source is { lift: InstanceType['lift'] } {\n return isFunction(source?.lift);\n}\n\n/**\n * Creates an `OperatorFunction`. Used to define operators throughout the library in a concise way.\n * @param init The logic to connect the liftedSource to the subscriber at the moment of subscription.\n */\nexport function operate(\n init: (liftedSource: Observable, subscriber: Subscriber) => (() => void) | void\n): OperatorFunction {\n return (source: Observable) => {\n if (hasLift(source)) {\n return source.lift(function (this: Subscriber, liftedSource: Observable) {\n try {\n return init(liftedSource, this);\n } catch (err) {\n this.error(err);\n }\n });\n }\n throw new TypeError('Unable to lift unknown Observable type');\n };\n}\n", "import { Subscriber } from '../Subscriber';\n\n/**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional teardown logic here. This will only be called on teardown if the\n * subscriber itself is not already closed. This is called after all other teardown logic is executed.\n */\nexport function createOperatorSubscriber(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n onFinalize?: () => void\n): Subscriber {\n return new OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize);\n}\n\n/**\n * A generic helper for allowing operators to be created with a Subscriber and\n * use closures to capture necessary state from the operator function itself.\n */\nexport class OperatorSubscriber extends Subscriber {\n /**\n * Creates an instance of an `OperatorSubscriber`.\n * @param destination The downstream subscriber.\n * @param onNext Handles next values, only called if this subscriber is not stopped or closed. Any\n * error that occurs in this function is caught and sent to the `error` method of this subscriber.\n * @param onError Handles errors from the subscription, any errors that occur in this handler are caught\n * and send to the `destination` error handler.\n * @param onComplete Handles completion notification from the subscription. Any errors that occur in\n * this handler are sent to the `destination` error handler.\n * @param onFinalize Additional finalization logic here. This will only be called on finalization if the\n * subscriber itself is not already closed. This is called after all other finalization logic is executed.\n * @param shouldUnsubscribe An optional check to see if an unsubscribe call should truly unsubscribe.\n * NOTE: This currently **ONLY** exists to support the strange behavior of {@link groupBy}, where unsubscription\n * to the resulting observable does not actually disconnect from the source if there are active subscriptions\n * to any grouped observable. (DO NOT EXPOSE OR USE EXTERNALLY!!!)\n */\n constructor(\n destination: Subscriber,\n onNext?: (value: T) => void,\n onComplete?: () => void,\n onError?: (err: any) => void,\n private onFinalize?: () => void,\n private shouldUnsubscribe?: () => boolean\n ) {\n // It's important - for performance reasons - that all of this class's\n // members are initialized and that they are always initialized in the same\n // order. This will ensure that all OperatorSubscriber instances have the\n // same hidden class in V8. This, in turn, will help keep the number of\n // hidden classes involved in property accesses within the base class as\n // low as possible. If the number of hidden classes involved exceeds four,\n // the property accesses will become megamorphic and performance penalties\n // will be incurred - i.e. inline caches won't be used.\n //\n // The reasons for ensuring all instances have the same hidden class are\n // further discussed in this blog post from Benedikt Meurer:\n // https://benediktmeurer.de/2018/03/23/impact-of-polymorphism-on-component-based-frameworks-like-react/\n super(destination);\n this._next = onNext\n ? function (this: OperatorSubscriber, value: T) {\n try {\n onNext(value);\n } catch (err) {\n destination.error(err);\n }\n }\n : super._next;\n this._error = onError\n ? function (this: OperatorSubscriber, err: any) {\n try {\n onError(err);\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._error;\n this._complete = onComplete\n ? function (this: OperatorSubscriber) {\n try {\n onComplete();\n } catch (err) {\n // Send any errors that occur down stream.\n destination.error(err);\n } finally {\n // Ensure finalization.\n this.unsubscribe();\n }\n }\n : super._complete;\n }\n\n unsubscribe() {\n if (!this.shouldUnsubscribe || this.shouldUnsubscribe()) {\n const { closed } = this;\n super.unsubscribe();\n // Execute additional teardown if we have any and we didn't already do so.\n !closed && this.onFinalize?.();\n }\n }\n}\n", "import { Subscription } from '../Subscription';\n\ninterface AnimationFrameProvider {\n schedule(callback: FrameRequestCallback): Subscription;\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n delegate:\n | {\n requestAnimationFrame: typeof requestAnimationFrame;\n cancelAnimationFrame: typeof cancelAnimationFrame;\n }\n | undefined;\n}\n\nexport const animationFrameProvider: AnimationFrameProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n schedule(callback) {\n let request = requestAnimationFrame;\n let cancel: typeof cancelAnimationFrame | undefined = cancelAnimationFrame;\n const { delegate } = animationFrameProvider;\n if (delegate) {\n request = delegate.requestAnimationFrame;\n cancel = delegate.cancelAnimationFrame;\n }\n const handle = request((timestamp) => {\n // Clear the cancel function. The request has been fulfilled, so\n // attempting to cancel the request upon unsubscription would be\n // pointless.\n cancel = undefined;\n callback(timestamp);\n });\n return new Subscription(() => cancel?.(handle));\n },\n requestAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.requestAnimationFrame || requestAnimationFrame)(...args);\n },\n cancelAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return (delegate?.cancelAnimationFrame || cancelAnimationFrame)(...args);\n },\n delegate: undefined,\n};\n", "import { createErrorClass } from './createErrorClass';\n\nexport interface ObjectUnsubscribedError extends Error {}\n\nexport interface ObjectUnsubscribedErrorCtor {\n /**\n * @deprecated Internal implementation detail. Do not construct error instances.\n * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n */\n new (): ObjectUnsubscribedError;\n}\n\n/**\n * An error thrown when an action is invalid because the object has been\n * unsubscribed.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n *\n * @class ObjectUnsubscribedError\n */\nexport const ObjectUnsubscribedError: ObjectUnsubscribedErrorCtor = createErrorClass(\n (_super) =>\n function ObjectUnsubscribedErrorImpl(this: any) {\n _super(this);\n this.name = 'ObjectUnsubscribedError';\n this.message = 'object unsubscribed';\n }\n);\n", "import { Operator } from './Operator';\nimport { Observable } from './Observable';\nimport { Subscriber } from './Subscriber';\nimport { Subscription, EMPTY_SUBSCRIPTION } from './Subscription';\nimport { Observer, SubscriptionLike, TeardownLogic } from './types';\nimport { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';\nimport { arrRemove } from './util/arrRemove';\nimport { errorContext } from './util/errorContext';\n\n/**\n * A Subject is a special type of Observable that allows values to be\n * multicasted to many Observers. Subjects are like EventEmitters.\n *\n * Every Subject is an Observable and an Observer. You can subscribe to a\n * Subject, and you can call next to feed values as well as error and complete.\n */\nexport class Subject extends Observable implements SubscriptionLike {\n closed = false;\n\n private currentObservers: Observer[] | null = null;\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n observers: Observer[] = [];\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n isStopped = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n hasError = false;\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n thrownError: any = null;\n\n /**\n * Creates a \"subject\" by basically gluing an observer to an observable.\n *\n * @nocollapse\n * @deprecated Recommended you do not use. Will be removed at some point in the future. Plans for replacement still under discussion.\n */\n static create: (...args: any[]) => any = (destination: Observer, source: Observable): AnonymousSubject => {\n return new AnonymousSubject(destination, source);\n };\n\n constructor() {\n // NOTE: This must be here to obscure Observable's constructor.\n super();\n }\n\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n lift(operator: Operator): Observable {\n const subject = new AnonymousSubject(this, this);\n subject.operator = operator as any;\n return subject as any;\n }\n\n /** @internal */\n protected _throwIfClosed() {\n if (this.closed) {\n throw new ObjectUnsubscribedError();\n }\n }\n\n next(value: T) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n if (!this.currentObservers) {\n this.currentObservers = Array.from(this.observers);\n }\n for (const observer of this.currentObservers) {\n observer.next(value);\n }\n }\n });\n }\n\n error(err: any) {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.hasError = this.isStopped = true;\n this.thrownError = err;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.error(err);\n }\n }\n });\n }\n\n complete() {\n errorContext(() => {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.isStopped = true;\n const { observers } = this;\n while (observers.length) {\n observers.shift()!.complete();\n }\n }\n });\n }\n\n unsubscribe() {\n this.isStopped = this.closed = true;\n this.observers = this.currentObservers = null!;\n }\n\n get observed() {\n return this.observers?.length > 0;\n }\n\n /** @internal */\n protected _trySubscribe(subscriber: Subscriber): TeardownLogic {\n this._throwIfClosed();\n return super._trySubscribe(subscriber);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._checkFinalizedStatuses(subscriber);\n return this._innerSubscribe(subscriber);\n }\n\n /** @internal */\n protected _innerSubscribe(subscriber: Subscriber) {\n const { hasError, isStopped, observers } = this;\n if (hasError || isStopped) {\n return EMPTY_SUBSCRIPTION;\n }\n this.currentObservers = null;\n observers.push(subscriber);\n return new Subscription(() => {\n this.currentObservers = null;\n arrRemove(observers, subscriber);\n });\n }\n\n /** @internal */\n protected _checkFinalizedStatuses(subscriber: Subscriber) {\n const { hasError, thrownError, isStopped } = this;\n if (hasError) {\n subscriber.error(thrownError);\n } else if (isStopped) {\n subscriber.complete();\n }\n }\n\n /**\n * Creates a new Observable with this Subject as the source. You can do this\n * to create custom Observer-side logic of the Subject and conceal it from\n * code that uses the Observable.\n * @return {Observable} Observable that the Subject casts to\n */\n asObservable(): Observable {\n const observable: any = new Observable();\n observable.source = this;\n return observable;\n }\n}\n\n/**\n * @class AnonymousSubject\n */\nexport class AnonymousSubject extends Subject {\n constructor(\n /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n public destination?: Observer,\n source?: Observable\n ) {\n super();\n this.source = source;\n }\n\n next(value: T) {\n this.destination?.next?.(value);\n }\n\n error(err: any) {\n this.destination?.error?.(err);\n }\n\n complete() {\n this.destination?.complete?.();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n return this.source?.subscribe(subscriber) ?? EMPTY_SUBSCRIPTION;\n }\n}\n", "import { Subject } from './Subject';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\n\n/**\n * A variant of Subject that requires an initial value and emits its current\n * value whenever it is subscribed to.\n *\n * @class BehaviorSubject\n */\nexport class BehaviorSubject extends Subject {\n constructor(private _value: T) {\n super();\n }\n\n get value(): T {\n return this.getValue();\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n const subscription = super._subscribe(subscriber);\n !subscription.closed && subscriber.next(this._value);\n return subscription;\n }\n\n getValue(): T {\n const { hasError, thrownError, _value } = this;\n if (hasError) {\n throw thrownError;\n }\n this._throwIfClosed();\n return _value;\n }\n\n next(value: T): void {\n super.next((this._value = value));\n }\n}\n", "import { TimestampProvider } from '../types';\n\ninterface DateTimestampProvider extends TimestampProvider {\n delegate: TimestampProvider | undefined;\n}\n\nexport const dateTimestampProvider: DateTimestampProvider = {\n now() {\n // Use the variable rather than `this` so that the function can be called\n // without being bound to the provider.\n return (dateTimestampProvider.delegate || Date).now();\n },\n delegate: undefined,\n};\n", "import { Subject } from './Subject';\nimport { TimestampProvider } from './types';\nimport { Subscriber } from './Subscriber';\nimport { Subscription } from './Subscription';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * A variant of {@link Subject} that \"replays\" old values to new subscribers by emitting them when they first subscribe.\n *\n * `ReplaySubject` has an internal buffer that will store a specified number of values that it has observed. Like `Subject`,\n * `ReplaySubject` \"observes\" values by having them passed to its `next` method. When it observes a value, it will store that\n * value for a time determined by the configuration of the `ReplaySubject`, as passed to its constructor.\n *\n * When a new subscriber subscribes to the `ReplaySubject` instance, it will synchronously emit all values in its buffer in\n * a First-In-First-Out (FIFO) manner. The `ReplaySubject` will also complete, if it has observed completion; and it will\n * error if it has observed an error.\n *\n * There are two main configuration items to be concerned with:\n *\n * 1. `bufferSize` - This will determine how many items are stored in the buffer, defaults to infinite.\n * 2. `windowTime` - The amount of time to hold a value in the buffer before removing it from the buffer.\n *\n * Both configurations may exist simultaneously. So if you would like to buffer a maximum of 3 values, as long as the values\n * are less than 2 seconds old, you could do so with a `new ReplaySubject(3, 2000)`.\n *\n * ### Differences with BehaviorSubject\n *\n * `BehaviorSubject` is similar to `new ReplaySubject(1)`, with a couple of exceptions:\n *\n * 1. `BehaviorSubject` comes \"primed\" with a single value upon construction.\n * 2. `ReplaySubject` will replay values, even after observing an error, where `BehaviorSubject` will not.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n * @see {@link shareReplay}\n */\nexport class ReplaySubject extends Subject {\n private _buffer: (T | number)[] = [];\n private _infiniteTimeWindow = true;\n\n /**\n * @param bufferSize The size of the buffer to replay on subscription\n * @param windowTime The amount of time the buffered items will stay buffered\n * @param timestampProvider An object with a `now()` method that provides the current timestamp. This is used to\n * calculate the amount of time something has been buffered.\n */\n constructor(\n private _bufferSize = Infinity,\n private _windowTime = Infinity,\n private _timestampProvider: TimestampProvider = dateTimestampProvider\n ) {\n super();\n this._infiniteTimeWindow = _windowTime === Infinity;\n this._bufferSize = Math.max(1, _bufferSize);\n this._windowTime = Math.max(1, _windowTime);\n }\n\n next(value: T): void {\n const { isStopped, _buffer, _infiniteTimeWindow, _timestampProvider, _windowTime } = this;\n if (!isStopped) {\n _buffer.push(value);\n !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);\n }\n this._trimBuffer();\n super.next(value);\n }\n\n /** @internal */\n protected _subscribe(subscriber: Subscriber): Subscription {\n this._throwIfClosed();\n this._trimBuffer();\n\n const subscription = this._innerSubscribe(subscriber);\n\n const { _infiniteTimeWindow, _buffer } = this;\n // We use a copy here, so reentrant code does not mutate our array while we're\n // emitting it to a new subscriber.\n const copy = _buffer.slice();\n for (let i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {\n subscriber.next(copy[i] as T);\n }\n\n this._checkFinalizedStatuses(subscriber);\n\n return subscription;\n }\n\n private _trimBuffer() {\n const { _bufferSize, _timestampProvider, _buffer, _infiniteTimeWindow } = this;\n // If we don't have an infinite buffer size, and we're over the length,\n // use splice to truncate the old buffer values off. Note that we have to\n // double the size for instances where we're not using an infinite time window\n // because we're storing the values and the timestamps in the same array.\n const adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;\n _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);\n\n // Now, if we're not in an infinite time window, remove all values where the time is\n // older than what is allowed.\n if (!_infiniteTimeWindow) {\n const now = _timestampProvider.now();\n let last = 0;\n // Search the array for the first timestamp that isn't expired and\n // truncate the buffer up to that point.\n for (let i = 1; i < _buffer.length && (_buffer[i] as number) <= now; i += 2) {\n last = i;\n }\n last && _buffer.splice(0, last + 1);\n }\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Subscription } from '../Subscription';\nimport { SchedulerAction } from '../types';\n\n/**\n * A unit of work to be executed in a `scheduler`. An action is typically\n * created from within a {@link SchedulerLike} and an RxJS user does not need to concern\n * themselves about creating and manipulating an Action.\n *\n * ```ts\n * class Action extends Subscription {\n * new (scheduler: Scheduler, work: (state?: T) => void);\n * schedule(state?: T, delay: number = 0): Subscription;\n * }\n * ```\n *\n * @class Action\n */\nexport class Action extends Subscription {\n constructor(scheduler: Scheduler, work: (this: SchedulerAction, state?: T) => void) {\n super();\n }\n /**\n * Schedules this action on its parent {@link SchedulerLike} for execution. May be passed\n * some context object, `state`. May happen at some point in the future,\n * according to the `delay` parameter, if specified.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler.\n * @return {void}\n */\n public schedule(state?: T, delay: number = 0): Subscription {\n return this;\n }\n}\n", "import type { TimerHandle } from './timerHandle';\ntype SetIntervalFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearIntervalFunction = (handle: TimerHandle) => void;\n\ninterface IntervalProvider {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n delegate:\n | {\n setInterval: SetIntervalFunction;\n clearInterval: ClearIntervalFunction;\n }\n | undefined;\n}\n\nexport const intervalProvider: IntervalProvider = {\n // When accessing the delegate, use the variable rather than `this` so that\n // the functions can be called without being bound to the provider.\n setInterval(handler: () => void, timeout?: number, ...args) {\n const { delegate } = intervalProvider;\n if (delegate?.setInterval) {\n return delegate.setInterval(handler, timeout, ...args);\n }\n return setInterval(handler, timeout, ...args);\n },\n clearInterval(handle) {\n const { delegate } = intervalProvider;\n return (delegate?.clearInterval || clearInterval)(handle as any);\n },\n delegate: undefined,\n};\n", "import { Action } from './Action';\nimport { SchedulerAction } from '../types';\nimport { Subscription } from '../Subscription';\nimport { AsyncScheduler } from './AsyncScheduler';\nimport { intervalProvider } from './intervalProvider';\nimport { arrRemove } from '../util/arrRemove';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncAction extends Action {\n public id: TimerHandle | undefined;\n public state?: T;\n // @ts-ignore: Property has no initializer and is not definitely assigned\n public delay: number;\n protected pending: boolean = false;\n\n constructor(protected scheduler: AsyncScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (this.closed) {\n return this;\n }\n\n // Always replace the current state with the new state.\n this.state = state;\n\n const id = this.id;\n const scheduler = this.scheduler;\n\n //\n // Important implementation note:\n //\n // Actions only execute once by default, unless rescheduled from within the\n // scheduled callback. This allows us to implement single and repeat\n // actions via the same code path, without adding API surface area, as well\n // as mimic traditional recursion but across asynchronous boundaries.\n //\n // However, JS runtimes and timers distinguish between intervals achieved by\n // serial `setTimeout` calls vs. a single `setInterval` call. An interval of\n // serial `setTimeout` calls can be individually delayed, which delays\n // scheduling the next `setTimeout`, and so on. `setInterval` attempts to\n // guarantee the interval callback will be invoked more precisely to the\n // interval period, regardless of load.\n //\n // Therefore, we use `setInterval` to schedule single and repeat actions.\n // If the action reschedules itself with the same delay, the interval is not\n // canceled. If the action doesn't reschedule, or reschedules with a\n // different delay, the interval will be canceled after scheduled callback\n // execution.\n //\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, delay);\n }\n\n // Set the pending flag indicating that this action has been scheduled, or\n // has recursively rescheduled itself.\n this.pending = true;\n\n this.delay = delay;\n // If this action has already an async Id, don't request a new one.\n this.id = this.id ?? this.requestAsyncId(scheduler, this.id, delay);\n\n return this;\n }\n\n protected requestAsyncId(scheduler: AsyncScheduler, _id?: TimerHandle, delay: number = 0): TimerHandle {\n return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n }\n\n protected recycleAsyncId(_scheduler: AsyncScheduler, id?: TimerHandle, delay: number | null = 0): TimerHandle | undefined {\n // If this action is rescheduled with the same delay time, don't clear the interval id.\n if (delay != null && this.delay === delay && this.pending === false) {\n return id;\n }\n // Otherwise, if the action's delay time is different from the current delay,\n // or the action has been rescheduled before it's executed, clear the interval id\n if (id != null) {\n intervalProvider.clearInterval(id);\n }\n\n return undefined;\n }\n\n /**\n * Immediately executes this action and the `work` it contains.\n * @return {any}\n */\n public execute(state: T, delay: number): any {\n if (this.closed) {\n return new Error('executing a cancelled action');\n }\n\n this.pending = false;\n const error = this._execute(state, delay);\n if (error) {\n return error;\n } else if (this.pending === false && this.id != null) {\n // Dequeue if the action didn't reschedule itself. Don't call\n // unsubscribe(), because the action could reschedule later.\n // For example:\n // ```\n // scheduler.schedule(function doWork(counter) {\n // /* ... I'm a busy worker bee ... */\n // var originalAction = this;\n // /* wait 100ms before rescheduling the action */\n // setTimeout(function () {\n // originalAction.schedule(counter + 1);\n // }, 100);\n // }, 1000);\n // ```\n this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n }\n }\n\n protected _execute(state: T, _delay: number): any {\n let errored: boolean = false;\n let errorValue: any;\n try {\n this.work(state);\n } catch (e) {\n errored = true;\n // HACK: Since code elsewhere is relying on the \"truthiness\" of the\n // return here, we can't have it return \"\" or 0 or false.\n // TODO: Clean this up when we refactor schedulers mid-version-8 or so.\n errorValue = e ? e : new Error('Scheduled action threw falsy error');\n }\n if (errored) {\n this.unsubscribe();\n return errorValue;\n }\n }\n\n unsubscribe() {\n if (!this.closed) {\n const { id, scheduler } = this;\n const { actions } = scheduler;\n\n this.work = this.state = this.scheduler = null!;\n this.pending = false;\n\n arrRemove(actions, this);\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, null);\n }\n\n this.delay = null!;\n super.unsubscribe();\n }\n }\n}\n", "import { Action } from './scheduler/Action';\nimport { Subscription } from './Subscription';\nimport { SchedulerLike, SchedulerAction } from './types';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\n\n/**\n * An execution context and a data structure to order tasks and schedule their\n * execution. Provides a notion of (potentially virtual) time, through the\n * `now()` getter method.\n *\n * Each unit of work in a Scheduler is called an `Action`.\n *\n * ```ts\n * class Scheduler {\n * now(): number;\n * schedule(work, delay?, state?): Subscription;\n * }\n * ```\n *\n * @class Scheduler\n * @deprecated Scheduler is an internal implementation detail of RxJS, and\n * should not be used directly. Rather, create your own class and implement\n * {@link SchedulerLike}. Will be made internal in v8.\n */\nexport class Scheduler implements SchedulerLike {\n public static now: () => number = dateTimestampProvider.now;\n\n constructor(private schedulerActionCtor: typeof Action, now: () => number = Scheduler.now) {\n this.now = now;\n }\n\n /**\n * A getter method that returns a number representing the current time\n * (at the time this function was called) according to the scheduler's own\n * internal clock.\n * @return {number} A number that represents the current time. May or may not\n * have a relation to wall-clock time. May or may not refer to a time unit\n * (e.g. milliseconds).\n */\n public now: () => number;\n\n /**\n * Schedules a function, `work`, for execution. May happen at some point in\n * the future, according to the `delay` parameter, if specified. May be passed\n * some context object, `state`, which will be passed to the `work` function.\n *\n * The given arguments will be processed an stored as an Action object in a\n * queue of actions.\n *\n * @param {function(state: ?T): ?Subscription} work A function representing a\n * task, or some unit of work to be executed by the Scheduler.\n * @param {number} [delay] Time to wait before executing the work, where the\n * time unit is implicit and defined by the Scheduler itself.\n * @param {T} [state] Some contextual data that the `work` function uses when\n * called by the Scheduler.\n * @return {Subscription} A subscription in order to be able to unsubscribe\n * the scheduled work.\n */\n public schedule(work: (this: SchedulerAction, state?: T) => void, delay: number = 0, state?: T): Subscription {\n return new this.schedulerActionCtor(this, work).schedule(state, delay);\n }\n}\n", "import { Scheduler } from '../Scheduler';\nimport { Action } from './Action';\nimport { AsyncAction } from './AsyncAction';\nimport { TimerHandle } from './timerHandle';\n\nexport class AsyncScheduler extends Scheduler {\n public actions: Array> = [];\n /**\n * A flag to indicate whether the Scheduler is currently executing a batch of\n * queued actions.\n * @type {boolean}\n * @internal\n */\n public _active: boolean = false;\n /**\n * An internal ID used to track the latest asynchronous task such as those\n * coming from `setTimeout`, `setInterval`, `requestAnimationFrame`, and\n * others.\n * @type {any}\n * @internal\n */\n public _scheduled: TimerHandle | undefined;\n\n constructor(SchedulerAction: typeof Action, now: () => number = Scheduler.now) {\n super(SchedulerAction, now);\n }\n\n public flush(action: AsyncAction): void {\n const { actions } = this;\n\n if (this._active) {\n actions.push(action);\n return;\n }\n\n let error: any;\n this._active = true;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions.shift()!)); // exhaust the scheduler queue\n\n this._active = false;\n\n if (error) {\n while ((action = actions.shift()!)) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\n/**\n *\n * Async Scheduler\n *\n * Schedule task as if you used setTimeout(task, duration)\n *\n * `async` scheduler schedules tasks asynchronously, by putting them on the JavaScript\n * event loop queue. It is best used to delay tasks in time or to schedule tasks repeating\n * in intervals.\n *\n * If you just want to \"defer\" task, that is to perform it right after currently\n * executing synchronous code ends (commonly achieved by `setTimeout(deferredTask, 0)`),\n * better choice will be the {@link asapScheduler} scheduler.\n *\n * ## Examples\n * Use async scheduler to delay task\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * const task = () => console.log('it works!');\n *\n * asyncScheduler.schedule(task, 2000);\n *\n * // After 2 seconds logs:\n * // \"it works!\"\n * ```\n *\n * Use async scheduler to repeat task in intervals\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * function task(state) {\n * console.log(state);\n * this.schedule(state + 1, 1000); // `this` references currently executing Action,\n * // which we reschedule with new state and delay\n * }\n *\n * asyncScheduler.schedule(task, 3000, 0);\n *\n * // Logs:\n * // 0 after 3s\n * // 1 after 4s\n * // 2 after 5s\n * // 3 after 6s\n * ```\n */\n\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\n\n/**\n * @deprecated Renamed to {@link asyncScheduler}. Will be removed in v8.\n */\nexport const async = asyncScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { Subscription } from '../Subscription';\nimport { QueueScheduler } from './QueueScheduler';\nimport { SchedulerAction } from '../types';\nimport { TimerHandle } from './timerHandle';\n\nexport class QueueAction extends AsyncAction {\n constructor(protected scheduler: QueueScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n public schedule(state?: T, delay: number = 0): Subscription {\n if (delay > 0) {\n return super.schedule(state, delay);\n }\n this.delay = delay;\n this.state = state;\n this.scheduler.flush(this);\n return this;\n }\n\n public execute(state: T, delay: number): any {\n return delay > 0 || this.closed ? super.execute(state, delay) : this._execute(state, delay);\n }\n\n protected requestAsyncId(scheduler: QueueScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n\n if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n\n // Otherwise flush the scheduler starting with this action.\n scheduler.flush(this);\n\n // HACK: In the past, this was returning `void`. However, `void` isn't a valid\n // `TimerHandle`, and generally the return value here isn't really used. So the\n // compromise is to return `0` which is both \"falsy\" and a valid `TimerHandle`,\n // as opposed to refactoring every other instanceo of `requestAsyncId`.\n return 0;\n }\n}\n", "import { AsyncScheduler } from './AsyncScheduler';\n\nexport class QueueScheduler extends AsyncScheduler {\n}\n", "import { QueueAction } from './QueueAction';\nimport { QueueScheduler } from './QueueScheduler';\n\n/**\n *\n * Queue Scheduler\n *\n * Put every next task on a queue, instead of executing it immediately\n *\n * `queue` scheduler, when used with delay, behaves the same as {@link asyncScheduler} scheduler.\n *\n * When used without delay, it schedules given task synchronously - executes it right when\n * it is scheduled. However when called recursively, that is when inside the scheduled task,\n * another task is scheduled with queue scheduler, instead of executing immediately as well,\n * that task will be put on a queue and wait for current one to finish.\n *\n * This means that when you execute task with `queue` scheduler, you are sure it will end\n * before any other task scheduled with that scheduler will start.\n *\n * ## Examples\n * Schedule recursively first, then do something\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(() => {\n * queueScheduler.schedule(() => console.log('second')); // will not happen now, but will be put on a queue\n *\n * console.log('first');\n * });\n *\n * // Logs:\n * // \"first\"\n * // \"second\"\n * ```\n *\n * Reschedule itself recursively\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(function(state) {\n * if (state !== 0) {\n * console.log('before', state);\n * this.schedule(state - 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * console.log('after', state);\n * }\n * }, 0, 3);\n *\n * // In scheduler that runs recursively, you would expect:\n * // \"before\", 3\n * // \"before\", 2\n * // \"before\", 1\n * // \"after\", 1\n * // \"after\", 2\n * // \"after\", 3\n *\n * // But with queue it logs:\n * // \"before\", 3\n * // \"after\", 3\n * // \"before\", 2\n * // \"after\", 2\n * // \"before\", 1\n * // \"after\", 1\n * ```\n */\n\nexport const queueScheduler = new QueueScheduler(QueueAction);\n\n/**\n * @deprecated Renamed to {@link queueScheduler}. Will be removed in v8.\n */\nexport const queue = queueScheduler;\n", "import { AsyncAction } from './AsyncAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\nimport { SchedulerAction } from '../types';\nimport { animationFrameProvider } from './animationFrameProvider';\nimport { TimerHandle } from './timerHandle';\n\nexport class AnimationFrameAction extends AsyncAction {\n constructor(protected scheduler: AnimationFrameScheduler, protected work: (this: SchedulerAction, state?: T) => void) {\n super(scheduler, work);\n }\n\n protected requestAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n // If delay is greater than 0, request as an async action.\n if (delay !== null && delay > 0) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n // Push the action to the end of the scheduler queue.\n scheduler.actions.push(this);\n // If an animation frame has already been requested, don't request another\n // one. If an animation frame hasn't been requested yet, request one. Return\n // the current animation frame request id.\n return scheduler._scheduled || (scheduler._scheduled = animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));\n }\n\n protected recycleAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined {\n // If delay exists and is greater than 0, or if the delay is null (the\n // action wasn't rescheduled) but was originally scheduled as an async\n // action, then recycle as an async action.\n if (delay != null ? delay > 0 : this.delay > 0) {\n return super.recycleAsyncId(scheduler, id, delay);\n }\n // If the scheduler queue has no remaining actions with the same async id,\n // cancel the requested animation frame and set the scheduled flag to\n // undefined so the next AnimationFrameAction will request its own.\n const { actions } = scheduler;\n if (id != null && actions[actions.length - 1]?.id !== id) {\n animationFrameProvider.cancelAnimationFrame(id as number);\n scheduler._scheduled = undefined;\n }\n // Return undefined so the action knows to request a new async id if it's rescheduled.\n return undefined;\n }\n}\n", "import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\n\nexport class AnimationFrameScheduler extends AsyncScheduler {\n public flush(action?: AsyncAction): void {\n this._active = true;\n // The async id that effects a call to flush is stored in _scheduled.\n // Before executing an action, it's necessary to check the action's async\n // id to determine whether it's supposed to be executed in the current\n // flush.\n // Previous implementations of this method used a count to determine this,\n // but that was unsound, as actions that are unsubscribed - i.e. cancelled -\n // are removed from the actions array and that can shift actions that are\n // scheduled to be executed in a subsequent flush into positions at which\n // they are executed within the current flush.\n const flushId = this._scheduled;\n this._scheduled = undefined;\n\n const { actions } = this;\n let error: any;\n action = action || actions.shift()!;\n\n do {\n if ((error = action.execute(action.state, action.delay))) {\n break;\n }\n } while ((action = actions[0]) && action.id === flushId && actions.shift());\n\n this._active = false;\n\n if (error) {\n while ((action = actions[0]) && action.id === flushId && actions.shift()) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n", "import { AnimationFrameAction } from './AnimationFrameAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\n\n/**\n *\n * Animation Frame Scheduler\n *\n * Perform task when `window.requestAnimationFrame` would fire\n *\n * When `animationFrame` scheduler is used with delay, it will fall back to {@link asyncScheduler} scheduler\n * behaviour.\n *\n * Without delay, `animationFrame` scheduler can be used to create smooth browser animations.\n * It makes sure scheduled task will happen just before next browser content repaint,\n * thus performing animations as efficiently as possible.\n *\n * ## Example\n * Schedule div height animation\n * ```ts\n * // html:
\n * import { animationFrameScheduler } from 'rxjs';\n *\n * const div = document.querySelector('div');\n *\n * animationFrameScheduler.schedule(function(height) {\n * div.style.height = height + \"px\";\n *\n * this.schedule(height + 1); // `this` references currently executing Action,\n * // which we reschedule with new state\n * }, 0, 0);\n *\n * // You will see a div element growing in height\n * ```\n */\n\nexport const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);\n\n/**\n * @deprecated Renamed to {@link animationFrameScheduler}. Will be removed in v8.\n */\nexport const animationFrame = animationFrameScheduler;\n", "import { Observable } from '../Observable';\nimport { SchedulerLike } from '../types';\n\n/**\n * A simple Observable that emits no items to the Observer and immediately\n * emits a complete notification.\n *\n * Just emits 'complete', and nothing else.\n *\n * ![](empty.png)\n *\n * A simple Observable that only emits the complete notification. It can be used\n * for composing with other Observables, such as in a {@link mergeMap}.\n *\n * ## Examples\n *\n * Log complete notification\n *\n * ```ts\n * import { EMPTY } from 'rxjs';\n *\n * EMPTY.subscribe({\n * next: () => console.log('Next'),\n * complete: () => console.log('Complete!')\n * });\n *\n * // Outputs\n * // Complete!\n * ```\n *\n * Emit the number 7, then complete\n *\n * ```ts\n * import { EMPTY, startWith } from 'rxjs';\n *\n * const result = EMPTY.pipe(startWith(7));\n * result.subscribe(x => console.log(x));\n *\n * // Outputs\n * // 7\n * ```\n *\n * Map and flatten only odd numbers to the sequence `'a'`, `'b'`, `'c'`\n *\n * ```ts\n * import { interval, mergeMap, of, EMPTY } from 'rxjs';\n *\n * const interval$ = interval(1000);\n * const result = interval$.pipe(\n * mergeMap(x => x % 2 === 1 ? of('a', 'b', 'c') : EMPTY),\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following to the console:\n * // x is equal to the count on the interval, e.g. (0, 1, 2, 3, ...)\n * // x will occur every 1000ms\n * // if x % 2 is equal to 1, print a, b, c (each on its own)\n * // if x % 2 is not equal to 1, nothing will be output\n * ```\n *\n * @see {@link Observable}\n * @see {@link NEVER}\n * @see {@link of}\n * @see {@link throwError}\n */\nexport const EMPTY = new Observable((subscriber) => subscriber.complete());\n\n/**\n * @param scheduler A {@link SchedulerLike} to use for scheduling\n * the emission of the complete notification.\n * @deprecated Replaced with the {@link EMPTY} constant or {@link scheduled} (e.g. `scheduled([], scheduler)`). Will be removed in v8.\n */\nexport function empty(scheduler?: SchedulerLike) {\n return scheduler ? emptyScheduled(scheduler) : EMPTY;\n}\n\nfunction emptyScheduled(scheduler: SchedulerLike) {\n return new Observable((subscriber) => scheduler.schedule(() => subscriber.complete()));\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport function isScheduler(value: any): value is SchedulerLike {\n return value && isFunction(value.schedule);\n}\n", "import { SchedulerLike } from '../types';\nimport { isFunction } from './isFunction';\nimport { isScheduler } from './isScheduler';\n\nfunction last(arr: T[]): T | undefined {\n return arr[arr.length - 1];\n}\n\nexport function popResultSelector(args: any[]): ((...args: unknown[]) => unknown) | undefined {\n return isFunction(last(args)) ? args.pop() : undefined;\n}\n\nexport function popScheduler(args: any[]): SchedulerLike | undefined {\n return isScheduler(last(args)) ? args.pop() : undefined;\n}\n\nexport function popNumber(args: any[], defaultValue: number): number {\n return typeof last(args) === 'number' ? args.pop()! : defaultValue;\n}\n", "export const isArrayLike = ((x: any): x is ArrayLike => x && typeof x.length === 'number' && typeof x !== 'function');", "import { isFunction } from \"./isFunction\";\n\n/**\n * Tests to see if the object is \"thennable\".\n * @param value the object to test\n */\nexport function isPromise(value: any): value is PromiseLike {\n return isFunction(value?.then);\n}\n", "import { InteropObservable } from '../types';\nimport { observable as Symbol_observable } from '../symbol/observable';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being Observable (but not necessary an Rx Observable) */\nexport function isInteropObservable(input: any): input is InteropObservable {\n return isFunction(input[Symbol_observable]);\n}\n", "import { isFunction } from './isFunction';\n\nexport function isAsyncIterable(obj: any): obj is AsyncIterable {\n return Symbol.asyncIterator && isFunction(obj?.[Symbol.asyncIterator]);\n}\n", "/**\n * Creates the TypeError to throw if an invalid object is passed to `from` or `scheduled`.\n * @param input The object that was passed.\n */\nexport function createInvalidObservableTypeError(input: any) {\n // TODO: We should create error codes that can be looked up, so this can be less verbose.\n return new TypeError(\n `You provided ${\n input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`\n } where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`\n );\n}\n", "export function getSymbolIterator(): symbol {\n if (typeof Symbol !== 'function' || !Symbol.iterator) {\n return '@@iterator' as any;\n }\n\n return Symbol.iterator;\n}\n\nexport const iterator = getSymbolIterator();\n", "import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\n\n/** Identifies an input as being an Iterable */\nexport function isIterable(input: any): input is Iterable {\n return isFunction(input?.[Symbol_iterator]);\n}\n", "import { ReadableStreamLike } from '../types';\nimport { isFunction } from './isFunction';\n\nexport async function* readableStreamLikeToAsyncGenerator(readableStream: ReadableStreamLike): AsyncGenerator {\n const reader = readableStream.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n return;\n }\n yield value!;\n }\n } finally {\n reader.releaseLock();\n }\n}\n\nexport function isReadableStreamLike(obj: any): obj is ReadableStreamLike {\n // We don't want to use instanceof checks because they would return\n // false for instances from another Realm, like an + + +
+
+ +

TinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based on the implementation in boost::uuid::details. +More...

+
#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <stdint.h>
+
+

Go to the source code of this file.

+ + + + + +

+Classes

class  sha1::SHA1
 A tiny SHA1 algorithm implementation used internally in the Crow server (specifically in crow/websocket.h). More...
 
+ + + + +

+Namespaces

 sha1
 Here is defined the SHA1 class.
 
+

Detailed Description

+

TinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based on the implementation in boost::uuid::details.

+
Author
SAURAV MOHAPATRA mohap.nosp@m.s@gm.nosp@m.ail.c.nosp@m.om
+
Date
2012-22
+

In this file are defined:

+
+ + + + + + \ No newline at end of file diff --git a/1.2/reference/_tiny_s_h_a1_8hpp_source.html b/1.2/reference/_tiny_s_h_a1_8hpp_source.html new file mode 100644 index 000000000..4d12b2cf9 --- /dev/null +++ b/1.2/reference/_tiny_s_h_a1_8hpp_source.html @@ -0,0 +1,332 @@ + + + + + + + + Crow: include/crow/TinySHA1.hpp Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
TinySHA1.hpp
+
+
+Go to the documentation of this file.
1 /*
+
2  * SHA1 Wikipedia Page: http://en.wikipedia.org/wiki/SHA-1
+
3  *
+
4  * Copyright (c) 2012-22 SAURAV MOHAPATRA <mohaps@gmail.com>
+
5  *
+
6  * Permission to use, copy, modify, and distribute this software for any
+
7  * purpose with or without fee is hereby granted, provided that the above
+
8  * copyright notice and this permission notice appear in all copies.
+
9  *
+
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
17  */
+
18 
+
19 /**
+
20  * \file TinySHA1.hpp
+
21  * \author SAURAV MOHAPATRA <mohaps@gmail.com>
+
22  * \date 2012-22
+
23  * \brief TinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based
+
24  * on the implementation in boost::uuid::details.
+
25  *
+
26  * In this file are defined:
+
27  * - sha1::SHA1
+
28  */
+
29 #ifndef _TINY_SHA1_HPP_
+
30 #define _TINY_SHA1_HPP_
+
31 #include <cstdio>
+
32 #include <cstdlib>
+
33 #include <cstring>
+
34 #include <stdint.h>
+
35 
+
36 /**
+
37  * \namespace sha1
+
38  * \brief Here is defined the SHA1 class
+
39  */
+
40 namespace sha1
+
41 {
+
42  /**
+
43  * \class SHA1
+
44  * \brief A tiny SHA1 algorithm implementation used internally in the
+
45  * Crow server (specifically in crow/websocket.h).
+
46  */
+
47  class SHA1
+
48  {
+
49  public:
+
50  typedef uint32_t digest32_t[5];
+
51  typedef uint8_t digest8_t[20];
+
52  inline static uint32_t LeftRotate(uint32_t value, size_t count) {
+
53  return (value << count) ^ (value >> (32-count));
+
54  }
+
55  SHA1(){ reset(); }
+
56  virtual ~SHA1() {}
+
57  SHA1(const SHA1& s) { *this = s; }
+
58  const SHA1& operator = (const SHA1& s) {
+
59  memcpy(m_digest, s.m_digest, 5 * sizeof(uint32_t));
+
60  memcpy(m_block, s.m_block, 64);
+
61  m_blockByteIndex = s.m_blockByteIndex;
+
62  m_byteCount = s.m_byteCount;
+
63  return *this;
+
64  }
+
65  SHA1& reset() {
+
66  m_digest[0] = 0x67452301;
+
67  m_digest[1] = 0xEFCDAB89;
+
68  m_digest[2] = 0x98BADCFE;
+
69  m_digest[3] = 0x10325476;
+
70  m_digest[4] = 0xC3D2E1F0;
+
71  m_blockByteIndex = 0;
+
72  m_byteCount = 0;
+
73  return *this;
+
74  }
+
75  SHA1& processByte(uint8_t octet) {
+
76  this->m_block[this->m_blockByteIndex++] = octet;
+
77  ++this->m_byteCount;
+
78  if(m_blockByteIndex == 64) {
+
79  this->m_blockByteIndex = 0;
+
80  processBlock();
+
81  }
+
82  return *this;
+
83  }
+
84  SHA1& processBlock(const void* const start, const void* const end) {
+
85  const uint8_t* begin = static_cast<const uint8_t*>(start);
+
86  const uint8_t* finish = static_cast<const uint8_t*>(end);
+
87  while(begin != finish) {
+
88  processByte(*begin);
+
89  begin++;
+
90  }
+
91  return *this;
+
92  }
+
93  SHA1& processBytes(const void* const data, size_t len) {
+
94  const uint8_t* block = static_cast<const uint8_t*>(data);
+
95  processBlock(block, block + len);
+
96  return *this;
+
97  }
+
98  const uint32_t* getDigest(digest32_t digest) {
+
99  size_t bitCount = this->m_byteCount * 8;
+
100  processByte(0x80);
+
101  if (this->m_blockByteIndex > 56) {
+
102  while (m_blockByteIndex != 0) {
+
103  processByte(0);
+
104  }
+
105  while (m_blockByteIndex < 56) {
+
106  processByte(0);
+
107  }
+
108  } else {
+
109  while (m_blockByteIndex < 56) {
+
110  processByte(0);
+
111  }
+
112  }
+
113  processByte(0);
+
114  processByte(0);
+
115  processByte(0);
+
116  processByte(0);
+
117  processByte( static_cast<unsigned char>((bitCount>>24) & 0xFF));
+
118  processByte( static_cast<unsigned char>((bitCount>>16) & 0xFF));
+
119  processByte( static_cast<unsigned char>((bitCount>>8 ) & 0xFF));
+
120  processByte( static_cast<unsigned char>((bitCount) & 0xFF));
+
121 
+
122  memcpy(digest, m_digest, 5 * sizeof(uint32_t));
+
123  return digest;
+
124  }
+
125  const uint8_t* getDigestBytes(digest8_t digest) {
+
126  digest32_t d32;
+
127  getDigest(d32);
+
128  size_t di = 0;
+
129  digest[di++] = ((d32[0] >> 24) & 0xFF);
+
130  digest[di++] = ((d32[0] >> 16) & 0xFF);
+
131  digest[di++] = ((d32[0] >> 8) & 0xFF);
+
132  digest[di++] = ((d32[0]) & 0xFF);
+
133 
+
134  digest[di++] = ((d32[1] >> 24) & 0xFF);
+
135  digest[di++] = ((d32[1] >> 16) & 0xFF);
+
136  digest[di++] = ((d32[1] >> 8) & 0xFF);
+
137  digest[di++] = ((d32[1]) & 0xFF);
+
138 
+
139  digest[di++] = ((d32[2] >> 24) & 0xFF);
+
140  digest[di++] = ((d32[2] >> 16) & 0xFF);
+
141  digest[di++] = ((d32[2] >> 8) & 0xFF);
+
142  digest[di++] = ((d32[2]) & 0xFF);
+
143 
+
144  digest[di++] = ((d32[3] >> 24) & 0xFF);
+
145  digest[di++] = ((d32[3] >> 16) & 0xFF);
+
146  digest[di++] = ((d32[3] >> 8) & 0xFF);
+
147  digest[di++] = ((d32[3]) & 0xFF);
+
148 
+
149  digest[di++] = ((d32[4] >> 24) & 0xFF);
+
150  digest[di++] = ((d32[4] >> 16) & 0xFF);
+
151  digest[di++] = ((d32[4] >> 8) & 0xFF);
+
152  digest[di++] = ((d32[4]) & 0xFF);
+
153  return digest;
+
154  }
+
155 
+
156  protected:
+
157  void processBlock() {
+
158  uint32_t w[80];
+
159  for (size_t i = 0; i < 16; i++) {
+
160  w[i] = (m_block[i*4 + 0] << 24);
+
161  w[i] |= (m_block[i*4 + 1] << 16);
+
162  w[i] |= (m_block[i*4 + 2] << 8);
+
163  w[i] |= (m_block[i*4 + 3]);
+
164  }
+
165  for (size_t i = 16; i < 80; i++) {
+
166  w[i] = LeftRotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1);
+
167  }
+
168 
+
169  uint32_t a = m_digest[0];
+
170  uint32_t b = m_digest[1];
+
171  uint32_t c = m_digest[2];
+
172  uint32_t d = m_digest[3];
+
173  uint32_t e = m_digest[4];
+
174 
+
175  for (std::size_t i=0; i<80; ++i) {
+
176  uint32_t f = 0;
+
177  uint32_t k = 0;
+
178 
+
179  if (i<20) {
+
180  f = (b & c) | (~b & d);
+
181  k = 0x5A827999;
+
182  } else if (i<40) {
+
183  f = b ^ c ^ d;
+
184  k = 0x6ED9EBA1;
+
185  } else if (i<60) {
+
186  f = (b & c) | (b & d) | (c & d);
+
187  k = 0x8F1BBCDC;
+
188  } else {
+
189  f = b ^ c ^ d;
+
190  k = 0xCA62C1D6;
+
191  }
+
192  uint32_t temp = LeftRotate(a, 5) + f + e + k + w[i];
+
193  e = d;
+
194  d = c;
+
195  c = LeftRotate(b, 30);
+
196  b = a;
+
197  a = temp;
+
198  }
+
199 
+
200  m_digest[0] += a;
+
201  m_digest[1] += b;
+
202  m_digest[2] += c;
+
203  m_digest[3] += d;
+
204  m_digest[4] += e;
+
205  }
+
206  private:
+
207  digest32_t m_digest;
+
208  uint8_t m_block[64];
+
209  size_t m_blockByteIndex;
+
210  size_t m_byteCount;
+
211  };
+
212 }
+
213 #endif
+
A tiny SHA1 algorithm implementation used internally in the Crow server (specifically in crow/websock...
Definition: TinySHA1.hpp:48
+
Here is defined the SHA1 class.
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/annotated.html b/1.2/reference/annotated.html new file mode 100644 index 000000000..bf3d69c1a --- /dev/null +++ b/1.2/reference/annotated.html @@ -0,0 +1,226 @@ + + + + + + + + Crow: Class List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Class List
+
+
+
Here are the classes, structs, unions and interfaces with brief descriptions:
+
[detail level 12345]
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 NcrowThe main namespace of the library. In this namespace is defined the most important classes and functions of the library
 Ndetail
 Nrouting_handler_call_helper
 Ccheck_before_handle_arity_3_const
 Ccheck_before_handle_arity_3
 Ccheck_after_handle_arity_3_const
 Ccheck_after_handle_arity_3
 Ccheck_global_call_false
 Cis_before_handle_arity_3_impl
 Cis_after_handle_arity_3_impl
 Cis_middleware_global
 Cmiddleware_call_criteria_only_global
 Cmiddleware_call_criteria_dynamic
 Cmiddleware_call_criteria_dynamic< false >
 Cmiddleware_call_criteria_dynamic< true >
 Cpartial_context
 Cpartial_context<>
 Ccontext
 Cmiddleware_indicesTypesafe wrapper for storing lists of middleware as their indices in the App
 Ctask_timerA class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 second
 Njson
 Ndetail
 CrvalueJSON read value
 CwvalueJSON write value
 Cwvalue_reader
 NmultipartEncapsulates anything related to processing and organizing multipart/xyz messages
 CheaderThe first part in a section, contains metadata about the part
 CpartOne part of the multipart message
 CmessageThe parsed multipart request/response
 Nmustache
 Cinvalid_template_exception
 Crendered_template
 CAction
 Ctemplate_tA mustache template object
 Nsession
 Cmulti_value
 CExpirationTrackerExpiration tracker keeps track of soonest-to-expire keys
 CCachedSessionCachedSessions are shared across requests
 NwebsocketNamespace that includes the Connection class and connection struct. Useful for WebSockets connection
 CconnectionA base class for websocket connection
 CConnectionA websocket connection
 CCrowThe main server application class
 Cci_hashHashing function for ci_map (unordered_multimap)
 Cci_key_eqEquals function for ci_map (unordered_multimap)
 Crouting_handle_result
 CConnectionAn HTTP connection
 Chttp_parser
 Chttp_parser_settings
 CrequestAn HTTP request
 CresponseHTTP response
 Cstatic_file_infoThis constains metadata (coming from the stat command) related to any static files associated with this response
 CServer
 CILogHandler
 CCerrLogHandler
 Clogger
 CILocalMiddlewareLocal middleware should extend ILocalMiddleware
 CCookieParser
 Ccontext
 CCookie
 CCORSRulesUsed for tuning CORS policies
 CCORSHandlerCORSHandler is a global middleware for setting CORS headers
 Ccontext
 CSessionMiddleware
 Ccontext
 CInMemoryStoreInMemoryStore stores all entries in memory
 CFileStore
 CUTF8
 Ccontext
 CHTTPParserA wrapper for nodejs/http-parser
 Cquery_stringA class to represent any data coming after the ? in the request URL into key-value pairs
 CreturnableAn abstract class that allows any other class to be returned by a handler
 CBaseRuleA base class for all rules
 CCatchallRule
 CWebSocketRuleA rule dealing with websockets
 CRuleParameterTraitsAllows the user to assign parameters using functions
 CDynamicRuleA rule that can change its parameters during runtime
 CTaggedRuleDefault rule created when CROW_ROUTE is called
 CTrieA search tree
 CNode
 CBlueprintA blueprint can be considered a smaller section of a Crow app, specifically where the router is conecerned
 CRouterHandles matching requests to existing rules and upgrade requests
 CSocketAdaptorA wrapper for the asio::ip::tcp::socket and asio::ssl::stream
 CSSLAdaptor
 Nsha1Here is defined the SHA1 class
 CSHA1A tiny SHA1 algorithm implementation used internally in the Crow server (specifically in crow/websocket.h)
+
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/annotated_dup.js b/1.2/reference/annotated_dup.js new file mode 100644 index 000000000..fba9425db --- /dev/null +++ b/1.2/reference/annotated_dup.js @@ -0,0 +1,111 @@ +var annotated_dup = +[ + [ "crow", "namespacecrow.html", [ + [ "detail", null, [ + [ "routing_handler_call_helper", null, [ + [ "call_pair", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair" ], + [ "call_params", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params" ], + [ "call", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call.html", null ], + [ "call< F, NInt, NUint, NDouble, NString, black_magic::S< int64_t, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4" ], + [ "call< F, NInt, NUint, NDouble, NString, black_magic::S< uint64_t, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef" ], + [ "call< F, NInt, NUint, NDouble, NString, black_magic::S< double, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5" ], + [ "call< F, NInt, NUint, NDouble, NString, black_magic::S< std::string, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4" ], + [ "call< F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S< Args1... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8" ], + [ "Wrapped", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped" ] + ] ], + [ "check_before_handle_arity_3_const", "structcrow_1_1detail_1_1check__before__handle__arity__3__const.html", [ + [ "get", "structcrow_1_1detail_1_1check__before__handle__arity__3__const_1_1get.html", null ] + ] ], + [ "check_before_handle_arity_3", "structcrow_1_1detail_1_1check__before__handle__arity__3.html", [ + [ "get", "structcrow_1_1detail_1_1check__before__handle__arity__3_1_1get.html", null ] + ] ], + [ "check_after_handle_arity_3_const", "structcrow_1_1detail_1_1check__after__handle__arity__3__const.html", [ + [ "get", "structcrow_1_1detail_1_1check__after__handle__arity__3__const_1_1get.html", null ] + ] ], + [ "check_after_handle_arity_3", "structcrow_1_1detail_1_1check__after__handle__arity__3.html", [ + [ "get", "structcrow_1_1detail_1_1check__after__handle__arity__3_1_1get.html", null ] + ] ], + [ "check_global_call_false", "structcrow_1_1detail_1_1check__global__call__false.html", [ + [ "get", "structcrow_1_1detail_1_1check__global__call__false_1_1get.html", null ] + ] ], + [ "is_before_handle_arity_3_impl", "structcrow_1_1detail_1_1is__before__handle__arity__3__impl.html", null ], + [ "is_after_handle_arity_3_impl", "structcrow_1_1detail_1_1is__after__handle__arity__3__impl.html", null ], + [ "is_middleware_global", "structcrow_1_1detail_1_1is__middleware__global.html", null ], + [ "middleware_call_criteria_only_global", "structcrow_1_1detail_1_1middleware__call__criteria__only__global.html", "structcrow_1_1detail_1_1middleware__call__criteria__only__global" ], + [ "middleware_call_criteria_dynamic", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic.html", null ], + [ "middleware_call_criteria_dynamic< false >", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.html", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4" ], + [ "middleware_call_criteria_dynamic< true >", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.html", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4" ], + [ "partial_context", "structcrow_1_1detail_1_1partial__context.html", "structcrow_1_1detail_1_1partial__context" ], + [ "partial_context<>", "structcrow_1_1detail_1_1partial__context_3_4.html", "structcrow_1_1detail_1_1partial__context_3_4" ], + [ "context", "structcrow_1_1detail_1_1context.html", "structcrow_1_1detail_1_1context" ], + [ "middleware_indices", "structcrow_1_1detail_1_1middleware__indices.html", "structcrow_1_1detail_1_1middleware__indices" ], + [ "task_timer", "classcrow_1_1detail_1_1task__timer.html", "classcrow_1_1detail_1_1task__timer" ] + ] ], + [ "json", null, [ + [ "detail", null, [ + [ "r_string", "structcrow_1_1json_1_1detail_1_1r__string.html", "structcrow_1_1json_1_1detail_1_1r__string" ] + ] ], + [ "rvalue", "classcrow_1_1json_1_1rvalue.html", "classcrow_1_1json_1_1rvalue" ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html", "classcrow_1_1json_1_1wvalue" ], + [ "wvalue_reader", "structcrow_1_1json_1_1wvalue__reader.html", "structcrow_1_1json_1_1wvalue__reader" ] + ] ], + [ "multipart", "namespacecrow_1_1multipart.html", [ + [ "header", "structcrow_1_1multipart_1_1header.html", "structcrow_1_1multipart_1_1header" ], + [ "part", "structcrow_1_1multipart_1_1part.html", "structcrow_1_1multipart_1_1part" ], + [ "message", "structcrow_1_1multipart_1_1message.html", "structcrow_1_1multipart_1_1message" ] + ] ], + [ "mustache", null, [ + [ "invalid_template_exception", "classcrow_1_1mustache_1_1invalid__template__exception.html", "classcrow_1_1mustache_1_1invalid__template__exception" ], + [ "rendered_template", "structcrow_1_1mustache_1_1rendered__template.html", "structcrow_1_1mustache_1_1rendered__template" ], + [ "Action", "structcrow_1_1mustache_1_1_action.html", "structcrow_1_1mustache_1_1_action" ], + [ "template_t", "classcrow_1_1mustache_1_1template__t.html", "classcrow_1_1mustache_1_1template__t" ] + ] ], + [ "session", null, [ + [ "multi_value", "structcrow_1_1session_1_1multi__value.html", "structcrow_1_1session_1_1multi__value" ], + [ "ExpirationTracker", "structcrow_1_1session_1_1_expiration_tracker.html", "structcrow_1_1session_1_1_expiration_tracker" ], + [ "CachedSession", "structcrow_1_1session_1_1_cached_session.html", "structcrow_1_1session_1_1_cached_session" ] + ] ], + [ "websocket", "namespacecrow_1_1websocket.html", [ + [ "connection", "structcrow_1_1websocket_1_1connection.html", "structcrow_1_1websocket_1_1connection" ], + [ "Connection", "classcrow_1_1websocket_1_1_connection.html", "classcrow_1_1websocket_1_1_connection" ] + ] ], + [ "Crow", "classcrow_1_1_crow.html", "classcrow_1_1_crow" ], + [ "ci_hash", "structcrow_1_1ci__hash.html", "structcrow_1_1ci__hash" ], + [ "ci_key_eq", "structcrow_1_1ci__key__eq.html", "structcrow_1_1ci__key__eq" ], + [ "routing_handle_result", "structcrow_1_1routing__handle__result.html", "structcrow_1_1routing__handle__result" ], + [ "Connection", "classcrow_1_1_connection.html", "classcrow_1_1_connection" ], + [ "http_parser", "structcrow_1_1http__parser.html", "structcrow_1_1http__parser" ], + [ "http_parser_settings", "structcrow_1_1http__parser__settings.html", "structcrow_1_1http__parser__settings" ], + [ "request", "structcrow_1_1request.html", "structcrow_1_1request" ], + [ "response", "structcrow_1_1response.html", "structcrow_1_1response" ], + [ "Server", "classcrow_1_1_server.html", "classcrow_1_1_server" ], + [ "ILogHandler", "classcrow_1_1_i_log_handler.html", "classcrow_1_1_i_log_handler" ], + [ "CerrLogHandler", "classcrow_1_1_cerr_log_handler.html", "classcrow_1_1_cerr_log_handler" ], + [ "logger", "classcrow_1_1logger.html", "classcrow_1_1logger" ], + [ "ILocalMiddleware", "structcrow_1_1_i_local_middleware.html", "structcrow_1_1_i_local_middleware" ], + [ "CookieParser", "structcrow_1_1_cookie_parser.html", "structcrow_1_1_cookie_parser" ], + [ "CORSRules", "structcrow_1_1_c_o_r_s_rules.html", "structcrow_1_1_c_o_r_s_rules" ], + [ "CORSHandler", "structcrow_1_1_c_o_r_s_handler.html", "structcrow_1_1_c_o_r_s_handler" ], + [ "SessionMiddleware", "structcrow_1_1_session_middleware.html", "structcrow_1_1_session_middleware" ], + [ "InMemoryStore", "structcrow_1_1_in_memory_store.html", "structcrow_1_1_in_memory_store" ], + [ "FileStore", "structcrow_1_1_file_store.html", "structcrow_1_1_file_store" ], + [ "UTF8", "structcrow_1_1_u_t_f8.html", "structcrow_1_1_u_t_f8" ], + [ "HTTPParser", "structcrow_1_1_h_t_t_p_parser.html", "structcrow_1_1_h_t_t_p_parser" ], + [ "query_string", "classcrow_1_1query__string.html", "classcrow_1_1query__string" ], + [ "returnable", "structcrow_1_1returnable.html", "structcrow_1_1returnable" ], + [ "BaseRule", "classcrow_1_1_base_rule.html", "classcrow_1_1_base_rule" ], + [ "CatchallRule", "classcrow_1_1_catchall_rule.html", "classcrow_1_1_catchall_rule" ], + [ "WebSocketRule", "classcrow_1_1_web_socket_rule.html", "classcrow_1_1_web_socket_rule" ], + [ "RuleParameterTraits", "structcrow_1_1_rule_parameter_traits.html", "structcrow_1_1_rule_parameter_traits" ], + [ "DynamicRule", "classcrow_1_1_dynamic_rule.html", "classcrow_1_1_dynamic_rule" ], + [ "TaggedRule", "classcrow_1_1_tagged_rule.html", "classcrow_1_1_tagged_rule" ], + [ "Trie", "classcrow_1_1_trie.html", "classcrow_1_1_trie" ], + [ "Blueprint", "classcrow_1_1_blueprint.html", "classcrow_1_1_blueprint" ], + [ "Router", "classcrow_1_1_router.html", "classcrow_1_1_router" ], + [ "SocketAdaptor", "structcrow_1_1_socket_adaptor.html", "structcrow_1_1_socket_adaptor" ], + [ "SSLAdaptor", "structcrow_1_1_s_s_l_adaptor.html", "structcrow_1_1_s_s_l_adaptor" ] + ] ], + [ "sha1", "namespacesha1.html", [ + [ "SHA1", "classsha1_1_1_s_h_a1.html", "classsha1_1_1_s_h_a1" ] + ] ] +]; \ No newline at end of file diff --git a/1.2/reference/app_8h.html b/1.2/reference/app_8h.html new file mode 100644 index 000000000..9c5ea2343 --- /dev/null +++ b/1.2/reference/app_8h.html @@ -0,0 +1,419 @@ + + + + + + + + Crow: include/crow/app.h File Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
app.h File Reference
+
+
+ +

This file includes the definition of the crow::Crow class, the crow::App and crow::SimpleApp aliases, and some macros. +More...

+
#include <chrono>
+#include <string>
+#include <functional>
+#include <memory>
+#include <future>
+#include <cstdint>
+#include <type_traits>
+#include <thread>
+#include <condition_variable>
+#include "crow/version.h"
+#include "crow/settings.h"
+#include "crow/logging.h"
+#include "crow/utility.h"
+#include "crow/routing.h"
+#include "crow/middleware_context.h"
+#include "crow/http_request.h"
+#include "crow/http_server.h"
+#include "crow/task_timer.h"
+#include "crow/websocket.h"
+#include "crow/compression.h"
+
+

Go to the source code of this file.

+ + + + + +

+Classes

class  crow::Crow< Middlewares >
 The main server application class. More...
 
+ + + + +

+Namespaces

 crow
 The main namespace of the library. In this namespace is defined the most important classes and functions of the library.
 
+ + + + + + + + + + + + + + + + + + + +

+Macros

#define CROW_ROUTE(app, url)   app.template route<crow::black_magic::get_parameter_tag(url)>(url)
 Creates a route for app using a rule. More...
 
#define CROW_BP_ROUTE(blueprint, url)   blueprint.new_rule_tagged<crow::black_magic::get_parameter_tag(url)>(url)
 Creates a route for a blueprint using a rule. More...
 
#define CROW_WEBSOCKET_ROUTE(app, url)   app.route<crow::black_magic::get_parameter_tag(url)>(url).websocket<std::remove_reference<decltype(app)>::type>(&app)
 Defines WebSocket route for app. More...
 
#define CROW_MIDDLEWARES(app, ...)   template middlewares<typename std::remove_reference<decltype(app)>::type, __VA_ARGS__>()
 Enable a Middleware for an specific route in app or blueprint. More...
 
#define CROW_CATCHALL_ROUTE(app)   app.catchall_route()
 Defines a custom catchall route for app using a custom rule. More...
 
#define CROW_BP_CATCHALL_ROUTE(blueprint)   blueprint.catchall_rule()
 Defines a custom catchall route for blueprint using a custom rule. More...
 
+ + + + + + + + + + +

+Typedefs

+using crow::ssl_context_t = asio::ssl::context
 
+template<typename... Middlewares>
using crow::App = Crow< Middlewares... >
 Alias of Crow<Middlewares...>. Useful if you want a instance of an Crow application that require Middlewares.
 
+using crow::SimpleApp = Crow<>
 Alias of Crow<>. Useful if you want a instance of an Crow application that doesn't require of Middlewares.
 
+

Detailed Description

+

This file includes the definition of the crow::Crow class, the crow::App and crow::SimpleApp aliases, and some macros.

+

In this file are defined:

+

Macro Definition Documentation

+ +

◆ CROW_BP_CATCHALL_ROUTE

+ +
+
+ + + + + + + + +
#define CROW_BP_CATCHALL_ROUTE( blueprint)   blueprint.catchall_rule()
+
+ +

Defines a custom catchall route for blueprint using a custom rule.

+

It defines a handler when the client make a request for an undefined route in the blueprint.

+
See also
Page of the guide "Blueprint" (Define a custom Catchall route).
+ +
+
+ +

◆ CROW_BP_ROUTE

+ +
+
+ + + + + + + + + + + + + + + + + + +
#define CROW_BP_ROUTE( blueprint,
 url 
)   blueprint.new_rule_tagged<crow::black_magic::get_parameter_tag(url)>(url)
+
+ +

Creates a route for a blueprint using a rule.

+

It may use crow::Blueprint::new_rule_dynamic or crow::Blueprint::new_rule_tagged to define a new rule for an given blueprint. It's usage is similar to CROW_ROUTE macro:

+
+
CROW_BP_ROUTE(my_bp, "/")
+
([](){
+
return "<h1>Hello, world!</h1>";
+
});
+
#define CROW_BP_ROUTE(blueprint, url)
Creates a route for a blueprint using a rule.
Definition: app.h:94
+
A blueprint can be considered a smaller section of a Crow app, specifically where the router is conec...
Definition: routing.h:1104
+

This is the recommended way to define routes in a crow blueprint because of its compile-time capabilities.

+
See also
Page of the guide "Blueprints".
+ +
+
+ +

◆ CROW_CATCHALL_ROUTE

+ +
+
+ + + + + + + + +
#define CROW_CATCHALL_ROUTE( app)   app.catchall_route()
+
+ +

Defines a custom catchall route for app using a custom rule.

+

It defines a handler when the client make a request for an undefined route. Instead of just reply with a 404 status code (default behavior), you can define a custom handler using this macro.

+
See also
Page of the guide "Routes" (Catchall routes).
+ +
+
+ +

◆ CROW_MIDDLEWARES

+ +
+
+ + + + + + + + + + + + + + + + + + +
#define CROW_MIDDLEWARES( app,
 ... 
)   template middlewares<typename std::remove_reference<decltype(app)>::type, __VA_ARGS__>()
+
+ +

Enable a Middleware for an specific route in app or blueprint.

+

It defines the usage of a Middleware in one route. And it can be used in both crow::SimpleApp (and crow::App) instances and crow::Blueprint. Its usage syntax is like this:

+
auto app = crow::SimpleApp(); // or crow::App()
+
CROW_ROUTE(app, "/with_middleware")
+
.CROW_MIDDLEWARES(app, LocalMiddleware) // Can be used more than one
+
([]() { // middleware.
+
return "Hello world!";
+
});
+
#define CROW_ROUTE(app, url)
Creates a route for app using a rule.
Definition: app.h:70
+
Crow<> SimpleApp
Alias of Crow<>. Useful if you want a instance of an Crow application that doesn't require of Middlew...
Definition: app.h:775
+
See also
Page of the guide "Middlewares".
+ +
+
+ +

◆ CROW_ROUTE

+ +
+
+ + + + + + + + + + + + + + + + + + +
#define CROW_ROUTE( app,
 url 
)   app.template route<crow::black_magic::get_parameter_tag(url)>(url)
+
+ +

Creates a route for app using a rule.

+

It use crow::Crow::route_dynamic or crow::Crow::route to define a rule for your application. It's usage is like this:

+
auto app = crow::SimpleApp(); // or crow::App()
+
CROW_ROUTE(app, "/")
+
([](){
+
return "<h1>Hello, world!</h1>";
+
});
+

This is the recommended way to define routes in a crow application.

See also
Page of guide "Routes".
+ +
+
+ +

◆ CROW_WEBSOCKET_ROUTE

+ +
+
+ + + + + + + + + + + + + + + + + + +
#define CROW_WEBSOCKET_ROUTE( app,
 url 
)   app.route<crow::black_magic::get_parameter_tag(url)>(url).websocket<std::remove_reference<decltype(app)>::type>(&app)
+
+ +

Defines WebSocket route for app.

+

It binds a WebSocket route to app. Easy solution to implement WebSockets in your app. The usage syntax of this macro is like this:

+
auto app = crow::SimpleApp(); // or crow::App()
+ +
.onopen([&](crow::websocket::connection& conn){
+
do_something();
+
})
+
.onclose([&](crow::websocket::connection& conn, const std::string& reason){
+
do_something();
+
})
+
.onmessage([&](crow::websocket::connection&, const std::string& data, bool is_binary){
+
if (is_binary)
+
do_something(data);
+
else
+
do_something_else(data);
+
});
+
#define CROW_WEBSOCKET_ROUTE(app, url)
Defines WebSocket route for app.
Definition: app.h:123
+
A base class for websocket connection.
Definition: websocket.h:38
+
See also
Page of the guide "WebSockets".
+ +
+
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/app_8h.js b/1.2/reference/app_8h.js new file mode 100644 index 000000000..156623a5e --- /dev/null +++ b/1.2/reference/app_8h.js @@ -0,0 +1,13 @@ +var app_8h = +[ + [ "Crow", "classcrow_1_1_crow.html", "classcrow_1_1_crow" ], + [ "CROW_BP_CATCHALL_ROUTE", "app_8h.html#a8490c9a408955fcdb2237c694427754b", null ], + [ "CROW_BP_ROUTE", "app_8h.html#a479d0a674825fb289848dad80379efc7", null ], + [ "CROW_CATCHALL_ROUTE", "app_8h.html#a182dcf033f11eb89855a7b98bd6cfe02", null ], + [ "CROW_MIDDLEWARES", "app_8h.html#a12ac01cb1979c953ac1c1203114c5e0e", null ], + [ "CROW_ROUTE", "app_8h.html#a6aa7ec3a2f3ee3f17d5f9acd879e7381", null ], + [ "CROW_WEBSOCKET_ROUTE", "app_8h.html#a8deb011ba0eae4684d6c6bb13014c926", null ], + [ "App", "app_8h.html#a153c1bf24903d1a8629ef6eaf045110b", null ], + [ "SimpleApp", "app_8h.html#a3603179c9794548cac2c9990685178b4", null ], + [ "ssl_context_t", "app_8h.html#abdecc4861f896188f2c6ce6ec362d403", null ] +]; \ No newline at end of file diff --git a/1.2/reference/app_8h_source.html b/1.2/reference/app_8h_source.html new file mode 100644 index 000000000..c12d1c16b --- /dev/null +++ b/1.2/reference/app_8h_source.html @@ -0,0 +1,945 @@ + + + + + + + + Crow: include/crow/app.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
app.h
+
+
+Go to the documentation of this file.
1 /**
+
2  * \file crow/app.h
+
3  * \brief This file includes the definition of the crow::Crow class,
+
4  * the crow::App and crow::SimpleApp aliases, and some macros.
+
5  *
+
6  * In this file are defined:
+
7  * - crow::Crow
+
8  * - crow::App
+
9  * - crow::SimpleApp
+
10  * - \ref CROW_ROUTE
+
11  * - \ref CROW_BP_ROUTE
+
12  * - \ref CROW_WEBSOCKET_ROUTE
+
13  * - \ref CROW_MIDDLEWARES
+
14  * - \ref CROW_CATCHALL_ROUTE
+
15  * - \ref CROW_BP_CATCHALL_ROUTE
+
16  */
+
17 
+
18 #pragma once
+
19 
+
20 #include <chrono>
+
21 #include <string>
+
22 #include <functional>
+
23 #include <memory>
+
24 #include <future>
+
25 #include <cstdint>
+
26 #include <type_traits>
+
27 #include <thread>
+
28 #include <condition_variable>
+
29 
+
30 #include "crow/version.h"
+
31 #include "crow/settings.h"
+
32 #include "crow/logging.h"
+
33 #include "crow/utility.h"
+
34 #include "crow/routing.h"
+
35 #include "crow/middleware_context.h"
+
36 #include "crow/http_request.h"
+
37 #include "crow/http_server.h"
+
38 #include "crow/task_timer.h"
+
39 #include "crow/websocket.h"
+
40 #ifdef CROW_ENABLE_COMPRESSION
+
41 #include "crow/compression.h"
+
42 #endif // #ifdef CROW_ENABLE_COMPRESSION
+
43 
+
44 
+
45 #ifdef CROW_MSVC_WORKAROUND
+
46 
+
47 #define CROW_ROUTE(app, url) app.route_dynamic(url) // See the documentation in the comment below.
+
48 #define CROW_BP_ROUTE(blueprint, url) blueprint.new_rule_dynamic(url) // See the documentation in the comment below.
+
49 
+
50 #else // #ifdef CROW_MSVC_WORKAROUND
+
51 
+
52 /**
+
53  * \def CROW_ROUTE(app, url)
+
54  * \brief Creates a route for app using a rule.
+
55  *
+
56  * It use crow::Crow::route_dynamic or crow::Crow::route to define
+
57  * a rule for your application. It's usage is like this:
+
58  *
+
59  * ```cpp
+
60  * auto app = crow::SimpleApp(); // or crow::App()
+
61  * CROW_ROUTE(app, "/")
+
62  * ([](){
+
63  * return "<h1>Hello, world!</h1>";
+
64  * });
+
65  * ```
+
66  *
+
67  * This is the recommended way to define routes in a crow application.
+
68  * \see [Page of guide "Routes"](https://crowcpp.org/master/guides/routes/).
+
69  */
+
70 #define CROW_ROUTE(app, url) app.template route<crow::black_magic::get_parameter_tag(url)>(url)
+
71 
+
72 /**
+
73  * \def CROW_BP_ROUTE(blueprint, url)
+
74  * \brief Creates a route for a blueprint using a rule.
+
75  *
+
76  * It may use crow::Blueprint::new_rule_dynamic or
+
77  * crow::Blueprint::new_rule_tagged to define a new rule for
+
78  * an given blueprint. It's usage is similar
+
79  * to CROW_ROUTE macro:
+
80  *
+
81  * ```cpp
+
82  * crow::Blueprint my_bp();
+
83  * CROW_BP_ROUTE(my_bp, "/")
+
84  * ([](){
+
85  * return "<h1>Hello, world!</h1>";
+
86  * });
+
87  * ```
+
88  *
+
89  * This is the recommended way to define routes in a crow blueprint
+
90  * because of its compile-time capabilities.
+
91  *
+
92  * \see [Page of the guide "Blueprints"](https://crowcpp.org/master/guides/blueprints/).
+
93  */
+
94 #define CROW_BP_ROUTE(blueprint, url) blueprint.new_rule_tagged<crow::black_magic::get_parameter_tag(url)>(url)
+
95 
+
96 /**
+
97  * \def CROW_WEBSOCKET_ROUTE(app, url)
+
98  * \brief Defines WebSocket route for app.
+
99  *
+
100  * It binds a WebSocket route to app. Easy solution to implement
+
101  * WebSockets in your app. The usage syntax of this macro is
+
102  * like this:
+
103  *
+
104  * ```cpp
+
105  * auto app = crow::SimpleApp(); // or crow::App()
+
106  * CROW_WEBSOCKET_ROUTE(app, "/ws")
+
107  * .onopen([&](crow::websocket::connection& conn){
+
108  * do_something();
+
109  * })
+
110  * .onclose([&](crow::websocket::connection& conn, const std::string& reason){
+
111  * do_something();
+
112  * })
+
113  * .onmessage([&](crow::websocket::connection&, const std::string& data, bool is_binary){
+
114  * if (is_binary)
+
115  * do_something(data);
+
116  * else
+
117  * do_something_else(data);
+
118  * });
+
119  * ```
+
120  *
+
121  * \see [Page of the guide "WebSockets"](https://crowcpp.org/master/guides/websockets/).
+
122  */
+
123 #define CROW_WEBSOCKET_ROUTE(app, url) app.route<crow::black_magic::get_parameter_tag(url)>(url).websocket<std::remove_reference<decltype(app)>::type>(&app)
+
124 
+
125 /**
+
126  * \def CROW_MIDDLEWARES(app, ...)
+
127  * \brief Enable a Middleware for an specific route in app
+
128  * or blueprint.
+
129  *
+
130  * It defines the usage of a Middleware in one route. And it
+
131  * can be used in both crow::SimpleApp (and crow::App) instances and
+
132  * crow::Blueprint. Its usage syntax is like this:
+
133  *
+
134  * ```cpp
+
135  * auto app = crow::SimpleApp(); // or crow::App()
+
136  * CROW_ROUTE(app, "/with_middleware")
+
137  * .CROW_MIDDLEWARES(app, LocalMiddleware) // Can be used more than one
+
138  * ([]() { // middleware.
+
139  * return "Hello world!";
+
140  * });
+
141  * ```
+
142  *
+
143  * \see [Page of the guide "Middlewares"](https://crowcpp.org/master/guides/middleware/).
+
144  */
+
145 #define CROW_MIDDLEWARES(app, ...) template middlewares<typename std::remove_reference<decltype(app)>::type, __VA_ARGS__>()
+
146 
+
147 #endif // #ifdef CROW_MSVC_WORKAROUND
+
148 
+
149 /**
+
150  * \def CROW_CATCHALL_ROUTE(app)
+
151  * \brief Defines a custom catchall route for app using a
+
152  * custom rule.
+
153  *
+
154  * It defines a handler when the client make a request for an
+
155  * undefined route. Instead of just reply with a `404` status
+
156  * code (default behavior), you can define a custom handler
+
157  * using this macro.
+
158  *
+
159  * \see [Page of the guide "Routes" (Catchall routes)](https://crowcpp.org/master/guides/routes/#catchall-routes).
+
160  */
+
161 #define CROW_CATCHALL_ROUTE(app) app.catchall_route()
+
162 
+
163 /**
+
164  * \def CROW_BP_CATCHALL_ROUTE(blueprint)
+
165  * \brief Defines a custom catchall route for blueprint
+
166  * using a custom rule.
+
167  *
+
168  * It defines a handler when the client make a request for an
+
169  * undefined route in the blueprint.
+
170  *
+
171  * \see [Page of the guide "Blueprint" (Define a custom Catchall route)](https://crowcpp.org/master/guides/blueprints/#define-a-custom-catchall-route).
+
172  */
+
173 #define CROW_BP_CATCHALL_ROUTE(blueprint) blueprint.catchall_rule()
+
174 
+
175 
+
176 /**
+
177  * \namespace crow
+
178  * \brief The main namespace of the library. In this namespace
+
179  * is defined the most important classes and functions of the
+
180  * library.
+
181  *
+
182  * Within this namespace, the Crow class, Router class, Connection
+
183  * class, and other are defined.
+
184  */
+
185 namespace crow
+
186 {
+
187 #ifdef CROW_ENABLE_SSL
+
188  using ssl_context_t = asio::ssl::context;
+
189 #endif
+
190  /**
+
191  * \class Crow
+
192  * \brief The main server application class.
+
193  *
+
194  * Use crow::SimpleApp or crow::App<Middleware1, Middleware2, etc...> instead of
+
195  * directly instantiate this class.
+
196  */
+
197  template<typename... Middlewares>
+
198  class Crow
+
199  {
+
200  public:
+
201  /// \brief This is the crow application
+
202  using self_t = Crow;
+
203 
+
204  /// \brief The HTTP server
+
205  using server_t = Server<Crow, SocketAdaptor, Middlewares...>;
+
206 
+
207 #ifdef CROW_ENABLE_SSL
+
208  /// \brief An HTTP server that runs on SSL with an SSLAdaptor
+
209  using ssl_server_t = Server<Crow, SSLAdaptor, Middlewares...>;
+
210 #endif
+
211  Crow()
+
212  {}
+
213 
+
214  /// \brief Construct Crow with a subset of middleware
+
215  template<typename... Ts>
+
216  Crow(Ts&&... ts):
+
217  middlewares_(make_middleware_tuple(std::forward<Ts>(ts)...))
+
218  {}
+
219 
+
220  /// \brief Process an Upgrade request
+
221  ///
+
222  /// Currently used to upgrade an HTTP connection to a WebSocket connection
+
223  template<typename Adaptor>
+
224  void handle_upgrade(const request& req, response& res, Adaptor&& adaptor)
+
225  {
+
226  router_.handle_upgrade(req, res, adaptor);
+
227  }
+
228 
+
229  /// \brief Process only the method and URL of a request and provide a route (or an error response)
+
230  std::unique_ptr<routing_handle_result> handle_initial(request& req, response& res)
+
231  {
+
232  return router_.handle_initial(req, res);
+
233  }
+
234 
+
235  /// \brief Process the fully parsed request and generate a response for it
+
236  void handle(request& req, response& res, std::unique_ptr<routing_handle_result>& found)
+
237  {
+
238  router_.handle<self_t>(req, res, *found);
+
239  }
+
240 
+
241  /// \brief Process a fully parsed request from start to finish (primarily used for debugging)
+
242  void handle_full(request& req, response& res)
+
243  {
+
244  auto found = handle_initial(req, res);
+
245  if (found->rule_index)
+
246  handle(req, res, found);
+
247  }
+
248 
+
249  /// \brief Create a dynamic route using a rule (**Use CROW_ROUTE instead**)
+
250  DynamicRule& route_dynamic(const std::string& rule)
+
251  {
+
252  return router_.new_rule_dynamic(rule);
+
253  }
+
254 
+
255  /// \brief Create a route using a rule (**Use CROW_ROUTE instead**)
+
256  template<uint64_t Tag>
+
257 #ifdef CROW_GCC83_WORKAROUND
+
258  auto& route(const std::string& rule)
+
259 #else
+
260  auto route(const std::string& rule)
+
261 #endif
+
262 #if defined CROW_CAN_USE_CPP17 && !defined CROW_GCC83_WORKAROUND
+
263  -> typename std::invoke_result<decltype(&Router::new_rule_tagged<Tag>), Router, const std::string&>::type
+
264 #elif !defined CROW_GCC83_WORKAROUND
+
265  -> typename std::result_of<decltype (&Router::new_rule_tagged<Tag>)(Router, const std::string&)>::type
+
266 #endif
+
267  {
+
268  return router_.new_rule_tagged<Tag>(rule);
+
269  }
+
270 
+
271  /// \brief Create a route for any requests without a proper route (**Use CROW_CATCHALL_ROUTE instead**)
+ +
273  {
+
274  return router_.catchall_rule();
+
275  }
+
276 
+
277  /// \brief Set the default max payload size for websockets
+
278  self_t& websocket_max_payload(uint64_t max_payload)
+
279  {
+
280  max_payload_ = max_payload;
+
281  return *this;
+
282  }
+
283 
+
284  /// \brief Get the default max payload size for websockets
+ +
286  {
+
287  return max_payload_;
+
288  }
+
289 
+
290  self_t& signal_clear()
+
291  {
+
292  signals_.clear();
+
293  return *this;
+
294  }
+
295 
+
296  self_t& signal_add(int signal_number)
+
297  {
+
298  signals_.push_back(signal_number);
+
299  return *this;
+
300  }
+
301 
+
302  std::vector<int> signals()
+
303  {
+
304  return signals_;
+
305  }
+
306 
+
307  /// \brief Set the port that Crow will handle requests on
+
308  self_t& port(std::uint16_t port)
+
309  {
+
310  port_ = port;
+
311  return *this;
+
312  }
+
313 
+
314  /// \brief Get the port that Crow will handle requests on
+
315  std::uint16_t port()
+
316  {
+
317  return port_;
+
318  }
+
319 
+
320  /// \brief Set the connection timeout in seconds (default is 5)
+
321  self_t& timeout(std::uint8_t timeout)
+
322  {
+
323  timeout_ = timeout;
+
324  return *this;
+
325  }
+
326 
+
327  /// \brief Set the server name
+ +
329  {
+
330  server_name_ = server_name;
+
331  return *this;
+
332  }
+
333 
+
334  /// \brief The IP address that Crow will handle requests on (default is 0.0.0.0)
+
335  self_t& bindaddr(std::string bindaddr)
+
336  {
+
337  bindaddr_ = bindaddr;
+
338  return *this;
+
339  }
+
340 
+
341  /// \brief Get the address that Crow will handle requests on
+
342  std::string bindaddr()
+
343  {
+
344  return bindaddr_;
+
345  }
+
346 
+
347  /// \brief Run the server on multiple threads using all available threads
+ +
349  {
+
350  return concurrency(std::thread::hardware_concurrency());
+
351  }
+
352 
+
353  /// \brief Run the server on multiple threads using a specific number
+ +
355  {
+
356  if (concurrency < 2) // Crow can have a minimum of 2 threads running
+
357  concurrency = 2;
+
358  concurrency_ = concurrency;
+
359  return *this;
+
360  }
+
361 
+
362  /// \brief Get the number of threads that server is using
+
363  std::uint16_t concurrency()
+
364  {
+
365  return concurrency_;
+
366  }
+
367 
+
368  /// \brief Set the server's log level
+
369  ///
+
370  /// Possible values are:
+
371  /// - crow::LogLevel::Debug (0)
+
372  /// - crow::LogLevel::Info (1)
+
373  /// - crow::LogLevel::Warning (2)
+
374  /// - crow::LogLevel::Error (3)
+
375  /// - crow::LogLevel::Critical (4)
+
376  self_t& loglevel(LogLevel level)
+
377  {
+
378  crow::logger::setLogLevel(level);
+
379  return *this;
+
380  }
+
381 
+
382  /// \brief Set the response body size (in bytes) beyond which Crow automatically streams responses (Default is 1MiB)
+
383  ///
+
384  /// Any streamed response is unaffected by Crow's timer, and therefore won't timeout before a response is fully sent.
+
385  self_t& stream_threshold(size_t threshold)
+
386  {
+
387  res_stream_threshold_ = threshold;
+
388  return *this;
+
389  }
+
390 
+
391  /// \brief Get the response body size (in bytes) beyond which Crow automatically streams responses
+ +
393  {
+
394  return res_stream_threshold_;
+
395  }
+
396 
+
397 
+
398  self_t& register_blueprint(Blueprint& blueprint)
+
399  {
+
400  router_.register_blueprint(blueprint);
+
401  return *this;
+
402  }
+
403 
+
404  /// \brief Set the function to call to handle uncaught exceptions generated in routes (Default generates error 500).
+
405  ///
+
406  /// The function must have the following signature: void(crow::response&).
+
407  /// It must set the response passed in argument to the function, which will be sent back to the client.
+
408  /// See Router::default_exception_handler() for the default implementation.
+
409  template<typename Func>
+ +
411  {
+
412  router_.exception_handler() = std::forward<Func>(f);
+
413  return *this;
+
414  }
+
415 
+
416  std::function<void(crow::response&)>& exception_handler()
+
417  {
+
418  return router_.exception_handler();
+
419  }
+
420 
+
421  /// \brief Set a custom duration and function to run on every tick
+
422  template<typename Duration, typename Func>
+
423  self_t& tick(Duration d, Func f)
+
424  {
+
425  tick_interval_ = std::chrono::duration_cast<std::chrono::milliseconds>(d);
+
426  tick_function_ = f;
+
427  return *this;
+
428  }
+
429 
+
430 #ifdef CROW_ENABLE_COMPRESSION
+
431 
+
432  self_t& use_compression(compression::algorithm algorithm)
+
433  {
+
434  comp_algorithm_ = algorithm;
+
435  compression_used_ = true;
+
436  return *this;
+
437  }
+
438 
+
439  compression::algorithm compression_algorithm()
+
440  {
+
441  return comp_algorithm_;
+
442  }
+
443 
+
444  bool compression_used() const
+
445  {
+
446  return compression_used_;
+
447  }
+
448 #endif
+
449 
+
450  /// \brief Apply blueprints
+ +
452  {
+
453 #if defined(__APPLE__) || defined(__MACH__)
+
454  if (router_.blueprints().empty()) return;
+
455 #endif
+
456 
+
457  for (Blueprint* bp : router_.blueprints())
+
458  {
+
459  if (bp->static_dir().empty()) continue;
+
460 
+
461  auto static_dir_ = crow::utility::normalize_path(bp->static_dir());
+
462 
+
463  bp->new_rule_tagged<crow::black_magic::get_parameter_tag(CROW_STATIC_ENDPOINT)>(CROW_STATIC_ENDPOINT)([static_dir_](crow::response& res, std::string file_path_partial) {
+
464  utility::sanitize_filename(file_path_partial);
+
465  res.set_static_file_info_unsafe(static_dir_ + file_path_partial);
+
466  res.end();
+
467  });
+
468  }
+
469 
+
470  router_.validate_bp();
+
471  }
+
472 
+
473  /// \brief Go through the rules, upgrade them if possible, and add them to the list of rules
+ +
475  {
+
476  if (are_static_routes_added()) return;
+
477  auto static_dir_ = crow::utility::normalize_path(CROW_STATIC_DIRECTORY);
+
478 
+
479  route<crow::black_magic::get_parameter_tag(CROW_STATIC_ENDPOINT)>(CROW_STATIC_ENDPOINT)([static_dir_](crow::response& res, std::string file_path_partial) {
+
480  utility::sanitize_filename(file_path_partial);
+
481  res.set_static_file_info_unsafe(static_dir_ + file_path_partial);
+
482  res.end();
+
483  });
+
484  set_static_routes_added();
+
485  }
+
486 
+
487  /// \brief A wrapper for `validate()` in the router
+
488  void validate()
+
489  {
+
490  router_.validate();
+
491  }
+
492 
+
493  /// \brief Run the server
+
494  void run()
+
495  {
+
496 #ifndef CROW_DISABLE_STATIC_DIR
+
497  add_blueprint();
+
498  add_static_dir();
+
499 #endif
+
500  validate();
+
501 
+
502 #ifdef CROW_ENABLE_SSL
+
503  if (ssl_used_)
+
504  {
+
505  ssl_server_ = std::move(std::unique_ptr<ssl_server_t>(new ssl_server_t(this, bindaddr_, port_, server_name_, &middlewares_, concurrency_, timeout_, &ssl_context_)));
+
506  ssl_server_->set_tick_function(tick_interval_, tick_function_);
+
507  ssl_server_->signal_clear();
+
508  for (auto snum : signals_)
+
509  {
+
510  ssl_server_->signal_add(snum);
+
511  }
+
512  notify_server_start();
+
513  ssl_server_->run();
+
514  }
+
515  else
+
516 #endif
+
517  {
+
518  server_ = std::move(std::unique_ptr<server_t>(new server_t(this, bindaddr_, port_, server_name_, &middlewares_, concurrency_, timeout_, nullptr)));
+
519  server_->set_tick_function(tick_interval_, tick_function_);
+
520  for (auto snum : signals_)
+
521  {
+
522  server_->signal_add(snum);
+
523  }
+
524  notify_server_start();
+
525  server_->run();
+
526  }
+
527  }
+
528 
+
529  /// \brief Non-blocking version of \ref run()
+
530  ///
+
531  /// The output from this method needs to be saved into a variable!
+
532  /// Otherwise the call will be made on the same thread.
+
533  std::future<void> run_async()
+
534  {
+
535  return std::async(std::launch::async, [&] {
+
536  this->run();
+
537  });
+
538  }
+
539 
+
540  /// \brief Stop the server
+
541  void stop()
+
542  {
+
543 #ifdef CROW_ENABLE_SSL
+
544  if (ssl_used_)
+
545  {
+
546  if (ssl_server_) { ssl_server_->stop(); }
+
547  }
+
548  else
+
549 #endif
+
550  {
+
551  // TODO(EDev): Move these 6 lines to a method in http_server.
+
552  std::vector<crow::websocket::connection*> websockets_to_close = websockets_;
+
553  for (auto websocket : websockets_to_close)
+
554  {
+
555  CROW_LOG_INFO << "Quitting Websocket: " << websocket;
+
556  websocket->close("Server Application Terminated");
+
557  }
+
558  if (server_) { server_->stop(); }
+
559  }
+
560  }
+
561 
+
562  void add_websocket(crow::websocket::connection* conn)
+
563  {
+
564  websockets_.push_back(conn);
+
565  }
+
566 
+
567  void remove_websocket(crow::websocket::connection* conn)
+
568  {
+
569  websockets_.erase(std::remove(websockets_.begin(), websockets_.end(), conn), websockets_.end());
+
570  }
+
571 
+
572  /// \brief Print the routing paths defined for each HTTP method
+
573  void debug_print()
+
574  {
+
575  CROW_LOG_DEBUG << "Routing:";
+
576  router_.debug_print();
+
577  }
+
578 
+
579 
+
580 #ifdef CROW_ENABLE_SSL
+
581 
+
582  /// \brief Use certificate and key files for SSL
+
583  self_t& ssl_file(const std::string& crt_filename, const std::string& key_filename)
+
584  {
+
585  ssl_used_ = true;
+
586  ssl_context_.set_verify_mode(asio::ssl::verify_peer);
+
587  ssl_context_.set_verify_mode(asio::ssl::verify_client_once);
+
588  ssl_context_.use_certificate_file(crt_filename, ssl_context_t::pem);
+
589  ssl_context_.use_private_key_file(key_filename, ssl_context_t::pem);
+
590  ssl_context_.set_options(
+
591  asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::no_sslv3);
+
592  return *this;
+
593  }
+
594 
+
595  /// \brief Use `.pem` file for SSL
+
596  self_t& ssl_file(const std::string& pem_filename)
+
597  {
+
598  ssl_used_ = true;
+
599  ssl_context_.set_verify_mode(asio::ssl::verify_peer);
+
600  ssl_context_.set_verify_mode(asio::ssl::verify_client_once);
+
601  ssl_context_.load_verify_file(pem_filename);
+
602  ssl_context_.set_options(
+
603  asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::no_sslv3);
+
604  return *this;
+
605  }
+
606 
+
607  /// \brief Use certificate chain and key files for SSL
+
608  self_t& ssl_chainfile(const std::string& crt_filename, const std::string& key_filename)
+
609  {
+
610  ssl_used_ = true;
+
611  ssl_context_.set_verify_mode(asio::ssl::verify_peer);
+
612  ssl_context_.set_verify_mode(asio::ssl::verify_client_once);
+
613  ssl_context_.use_certificate_chain_file(crt_filename);
+
614  ssl_context_.use_private_key_file(key_filename, ssl_context_t::pem);
+
615  ssl_context_.set_options(
+
616  asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::no_sslv3);
+
617  return *this;
+
618  }
+
619 
+
620  self_t& ssl(asio::ssl::context&& ctx)
+
621  {
+
622  ssl_used_ = true;
+
623  ssl_context_ = std::move(ctx);
+
624  return *this;
+
625  }
+
626 
+
627  bool ssl_used() const
+
628  {
+
629  return ssl_used_;
+
630  }
+
631 #else
+
632 
+
633  template<typename T, typename... Remain>
+
634  self_t& ssl_file(T&&, Remain&&...)
+
635  {
+
636  // We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
+
637  static_assert(
+
638  // make static_assert dependent to T; always false
+
639  std::is_base_of<T, void>::value,
+
640  "Define CROW_ENABLE_SSL to enable ssl support.");
+
641  return *this;
+
642  }
+
643 
+
644  template<typename T, typename... Remain>
+
645  self_t& ssl_chainfile(T&&, Remain&&...)
+
646  {
+
647  // We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
+
648  static_assert(
+
649  // make static_assert dependent to T; always false
+
650  std::is_base_of<T, void>::value,
+
651  "Define CROW_ENABLE_SSL to enable ssl support.");
+
652  return *this;
+
653  }
+
654 
+
655  template<typename T>
+
656  self_t& ssl(T&&)
+
657  {
+
658  // We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
+
659  static_assert(
+
660  // make static_assert dependent to T; always false
+
661  std::is_base_of<T, void>::value,
+
662  "Define CROW_ENABLE_SSL to enable ssl support.");
+
663  return *this;
+
664  }
+
665 
+
666  bool ssl_used() const
+
667  {
+
668  return false;
+
669  }
+
670 #endif
+
671 
+
672  // middleware
+
673  using context_t = detail::context<Middlewares...>;
+
674  using mw_container_t = std::tuple<Middlewares...>;
+
675  template<typename T>
+
676  typename T::context& get_context(const request& req)
+
677  {
+
678  static_assert(black_magic::contains<T, Middlewares...>::value, "App doesn't have the specified middleware type.");
+
679  auto& ctx = *reinterpret_cast<context_t*>(req.middleware_context);
+
680  return ctx.template get<T>();
+
681  }
+
682 
+
683  template<typename T>
+
684  T& get_middleware()
+
685  {
+
686  return utility::get_element_by_type<T, Middlewares...>(middlewares_);
+
687  }
+
688 
+
689  /// \brief Wait until the server has properly started
+ +
691  {
+
692  {
+
693  std::unique_lock<std::mutex> lock(start_mutex_);
+
694  if (!server_started_)
+
695  cv_started_.wait(lock);
+
696  }
+
697  if (server_)
+
698  server_->wait_for_start();
+
699 #ifdef CROW_ENABLE_SSL
+
700  else if (ssl_server_)
+
701  ssl_server_->wait_for_start();
+
702 #endif
+
703  }
+
704 
+
705  private:
+
706  template<typename... Ts>
+
707  std::tuple<Middlewares...> make_middleware_tuple(Ts&&... ts)
+
708  {
+
709  auto fwd = std::forward_as_tuple((ts)...);
+
710  return std::make_tuple(
+
711  std::forward<Middlewares>(
+
712  black_magic::tuple_extract<Middlewares, decltype(fwd)>(fwd))...);
+
713  }
+
714 
+
715  /// \brief Notify anything using \ref wait_for_server_start() to proceed
+
716  void notify_server_start()
+
717  {
+
718  std::unique_lock<std::mutex> lock(start_mutex_);
+
719  server_started_ = true;
+
720  cv_started_.notify_all();
+
721  }
+
722 
+
723  void set_static_routes_added() {
+
724  static_routes_added_ = true;
+
725  }
+
726 
+
727  bool are_static_routes_added() {
+
728  return static_routes_added_;
+
729  }
+
730 
+
731  private:
+
732  std::uint8_t timeout_{5};
+
733  uint16_t port_ = 80;
+
734  uint16_t concurrency_ = 2;
+
735  uint64_t max_payload_{UINT64_MAX};
+
736  std::string server_name_ = std::string("Crow/") + VERSION;
+
737  std::string bindaddr_ = "0.0.0.0";
+
738  size_t res_stream_threshold_ = 1048576;
+
739  Router router_;
+
740  bool static_routes_added_{false};
+
741 
+
742 #ifdef CROW_ENABLE_COMPRESSION
+
743  compression::algorithm comp_algorithm_;
+
744  bool compression_used_{false};
+
745 #endif
+
746 
+
747  std::chrono::milliseconds tick_interval_;
+
748  std::function<void()> tick_function_;
+
749 
+
750  std::tuple<Middlewares...> middlewares_;
+
751 
+
752 #ifdef CROW_ENABLE_SSL
+
753  std::unique_ptr<ssl_server_t> ssl_server_;
+
754  bool ssl_used_{false};
+
755  ssl_context_t ssl_context_{asio::ssl::context::sslv23};
+
756 #endif
+
757 
+
758  std::unique_ptr<server_t> server_;
+
759 
+
760  std::vector<int> signals_{SIGINT, SIGTERM};
+
761 
+
762  bool server_started_{false};
+
763  std::condition_variable cv_started_;
+
764  std::mutex start_mutex_;
+
765  std::vector<crow::websocket::connection*> websockets_;
+
766  };
+
767 
+
768  /// \brief Alias of Crow<Middlewares...>. Useful if you want
+
769  /// a instance of an Crow application that require Middlewares
+
770  template<typename... Middlewares>
+
771  using App = Crow<Middlewares...>;
+
772 
+
773  /// \brief Alias of Crow<>. Useful if you want a instance of
+
774  /// an Crow application that doesn't require of Middlewares
+
775  using SimpleApp = Crow<>;
+
776 } // namespace crow
+
A blueprint can be considered a smaller section of a Crow app, specifically where the router is conec...
Definition: routing.h:1104
+
Definition: routing.h:342
+
The main server application class.
Definition: app.h:199
+
self_t & multithreaded()
Run the server on multiple threads using all available threads.
Definition: app.h:348
+
void stop()
Stop the server.
Definition: app.h:541
+
self_t & tick(Duration d, Func f)
Set a custom duration and function to run on every tick.
Definition: app.h:423
+
DynamicRule & route_dynamic(const std::string &rule)
Create a dynamic route using a rule (Use CROW_ROUTE instead)
Definition: app.h:250
+
size_t & stream_threshold()
Get the response body size (in bytes) beyond which Crow automatically streams responses.
Definition: app.h:392
+
void run()
Run the server.
Definition: app.h:494
+
self_t & websocket_max_payload(uint64_t max_payload)
Set the default max payload size for websockets.
Definition: app.h:278
+
self_t & port(std::uint16_t port)
Set the port that Crow will handle requests on.
Definition: app.h:308
+
uint64_t websocket_max_payload()
Get the default max payload size for websockets.
Definition: app.h:285
+
void add_static_dir()
Go through the rules, upgrade them if possible, and add them to the list of rules.
Definition: app.h:474
+
self_t & ssl_file(const std::string &pem_filename)
Use .pem file for SSL.
Definition: app.h:596
+
self_t & concurrency(std::uint16_t concurrency)
Run the server on multiple threads using a specific number.
Definition: app.h:354
+
self_t & timeout(std::uint8_t timeout)
Set the connection timeout in seconds (default is 5)
Definition: app.h:321
+
Crow self_t
This is the crow application.
Definition: app.h:202
+
Server< Crow, SocketAdaptor, Middlewares... > server_t
The HTTP server.
Definition: app.h:205
+
auto route(const std::string &rule) -> typename std::result_of< decltype(&Router::new_rule_tagged< Tag >)(Router, const std::string &)>::type
Create a route using a rule (Use CROW_ROUTE instead)
Definition: app.h:260
+
void wait_for_server_start()
Wait until the server has properly started.
Definition: app.h:690
+
void handle_upgrade(const request &req, response &res, Adaptor &&adaptor)
Process an Upgrade request.
Definition: app.h:224
+
self_t & bindaddr(std::string bindaddr)
The IP address that Crow will handle requests on (default is 0.0.0.0)
Definition: app.h:335
+
std::unique_ptr< routing_handle_result > handle_initial(request &req, response &res)
Process only the method and URL of a request and provide a route (or an error response)
Definition: app.h:230
+
self_t & loglevel(LogLevel level)
Set the server's log level.
Definition: app.h:376
+
void debug_print()
Print the routing paths defined for each HTTP method.
Definition: app.h:573
+
void handle(request &req, response &res, std::unique_ptr< routing_handle_result > &found)
Process the fully parsed request and generate a response for it.
Definition: app.h:236
+
self_t & exception_handler(Func &&f)
Set the function to call to handle uncaught exceptions generated in routes (Default generates error 5...
Definition: app.h:410
+
std::uint16_t port()
Get the port that Crow will handle requests on.
Definition: app.h:315
+
std::string bindaddr()
Get the address that Crow will handle requests on.
Definition: app.h:342
+
self_t & ssl_file(const std::string &crt_filename, const std::string &key_filename)
Use certificate and key files for SSL.
Definition: app.h:583
+
Server< Crow, SSLAdaptor, Middlewares... > ssl_server_t
An HTTP server that runs on SSL with an SSLAdaptor.
Definition: app.h:209
+
std::future< void > run_async()
Non-blocking version of run()
Definition: app.h:533
+
CatchallRule & catchall_route()
Create a route for any requests without a proper route (Use CROW_CATCHALL_ROUTE instead)
Definition: app.h:272
+
void validate()
A wrapper for validate() in the router.
Definition: app.h:488
+
Crow(Ts &&... ts)
Construct Crow with a subset of middleware.
Definition: app.h:216
+
std::uint16_t concurrency()
Get the number of threads that server is using.
Definition: app.h:363
+
void handle_full(request &req, response &res)
Process a fully parsed request from start to finish (primarily used for debugging)
Definition: app.h:242
+
self_t & ssl_chainfile(const std::string &crt_filename, const std::string &key_filename)
Use certificate chain and key files for SSL.
Definition: app.h:608
+
self_t & server_name(std::string server_name)
Set the server name.
Definition: app.h:328
+
self_t & stream_threshold(size_t threshold)
Set the response body size (in bytes) beyond which Crow automatically streams responses (Default is 1...
Definition: app.h:385
+
void add_blueprint()
Apply blueprints.
Definition: app.h:451
+
A rule that can change its parameters during runtime.
Definition: routing.h:575
+
Handles matching requests to existing rules and upgrade requests.
Definition: routing.h:1254
+
Definition: http_server.h:43
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
Definition: socket_adaptors.h:107
+
A wrapper for the asio::ip::tcp::socket and asio::ssl::stream.
Definition: socket_adaptors.h:39
+
An HTTP request.
Definition: http_request.h:36
+
HTTP response.
Definition: http_response.h:34
+
void end()
Set the response completion flag and call the handler (to send the response).
Definition: http_response.h:237
+
void set_static_file_info_unsafe(std::string path)
Return a static file as the response body without sanitizing the path (use set_static_file_info inste...
Definition: http_response.h:295
+
A base class for websocket connection.
Definition: websocket.h:38
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/bc_s.png b/1.2/reference/bc_s.png new file mode 100644 index 000000000..224b29aa9 Binary files /dev/null and b/1.2/reference/bc_s.png differ diff --git a/1.2/reference/bdwn.png b/1.2/reference/bdwn.png new file mode 100644 index 000000000..940a0b950 Binary files /dev/null and b/1.2/reference/bdwn.png differ diff --git a/1.2/reference/ci__map_8h_source.html b/1.2/reference/ci__map_8h_source.html new file mode 100644 index 000000000..992451277 --- /dev/null +++ b/1.2/reference/ci__map_8h_source.html @@ -0,0 +1,161 @@ + + + + + + + + Crow: include/crow/ci_map.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
ci_map.h
+
+
+
1 #pragma once
+
2 
+
3 #include <locale>
+
4 #include <unordered_map>
+
5 #include "crow/utility.h"
+
6 
+
7 namespace crow
+
8 {
+
9  /// Hashing function for ci_map (unordered_multimap).
+
10  struct ci_hash
+
11  {
+
12  size_t operator()(const std::string& key) const
+
13  {
+
14  std::size_t seed = 0;
+
15  std::locale locale;
+
16 
+
17  for (auto c : key)
+
18  hash_combine(seed, std::toupper(c, locale));
+
19 
+
20  return seed;
+
21  }
+
22 
+
23  private:
+
24  static inline void hash_combine(std::size_t& seed, char v)
+
25  {
+
26  std::hash<char> hasher;
+
27  seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+
28  }
+
29  };
+
30 
+
31  /// Equals function for ci_map (unordered_multimap).
+
32  struct ci_key_eq
+
33  {
+
34  bool operator()(const std::string& l, const std::string& r) const
+
35  {
+
36  return utility::string_equals(l, r);
+
37  }
+
38  };
+
39 
+
40  using ci_map = std::unordered_multimap<std::string, std::string, ci_hash, ci_key_eq>;
+
41 } // namespace crow
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
Hashing function for ci_map (unordered_multimap).
Definition: ci_map.h:11
+
Equals function for ci_map (unordered_multimap).
Definition: ci_map.h:33
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_base_rule-members.html b/1.2/reference/classcrow_1_1_base_rule-members.html new file mode 100644 index 000000000..8195f15ea --- /dev/null +++ b/1.2/reference/classcrow_1_1_base_rule-members.html @@ -0,0 +1,141 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::BaseRule Member List
+
+
+ +

This is the complete list of members for crow::BaseRule, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + +
added_ (defined in crow::BaseRule)crow::BaseRuleprotected
BaseRule(std::string rule) (defined in crow::BaseRule)crow::BaseRuleinline
Blueprint (defined in crow::BaseRule)crow::BaseRulefriend
custom_templates_base (defined in crow::BaseRule)crow::BaseRule
foreach_method(F f) (defined in crow::BaseRule)crow::BaseRuleinline
get_methods() (defined in crow::BaseRule)crow::BaseRuleinline
handle(request &, response &, const routing_params &)=0 (defined in crow::BaseRule)crow::BaseRulepure virtual
handle_upgrade(const request &, response &res, SocketAdaptor &&) (defined in crow::BaseRule)crow::BaseRuleinlinevirtual
handle_upgrade(const request &, response &res, SSLAdaptor &&) (defined in crow::BaseRule)crow::BaseRuleinlinevirtual
is_added() (defined in crow::BaseRule)crow::BaseRuleinline
methods_ (defined in crow::BaseRule)crow::BaseRuleprotected
mw_indices_ (defined in crow::BaseRule)crow::BaseRuleprotected
name_ (defined in crow::BaseRule)crow::BaseRuleprotected
Router (defined in crow::BaseRule)crow::BaseRulefriend
rule() (defined in crow::BaseRule)crow::BaseRuleinline
rule_ (defined in crow::BaseRule)crow::BaseRuleprotected
rule_to_upgrade_ (defined in crow::BaseRule)crow::BaseRuleprotected
RuleParameterTraits (defined in crow::BaseRule)crow::BaseRulefriend
set_added() (defined in crow::BaseRule)crow::BaseRuleinline
upgrade() (defined in crow::BaseRule)crow::BaseRuleinline
validate()=0 (defined in crow::BaseRule)crow::BaseRulepure virtual
~BaseRule() (defined in crow::BaseRule)crow::BaseRuleinlinevirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_base_rule.html b/1.2/reference/classcrow_1_1_base_rule.html new file mode 100644 index 000000000..41d1d7830 --- /dev/null +++ b/1.2/reference/classcrow_1_1_base_rule.html @@ -0,0 +1,224 @@ + + + + + + + + Crow: crow::BaseRule Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::BaseRule Class Referenceabstract
+
+
+ +

A base class for all rules. + More...

+ +

#include <routing.h>

+
+Inheritance diagram for crow::BaseRule:
+
+
+ + +crow::DynamicRule +crow::TaggedRule< Args > +crow::WebSocketRule< App > + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

BaseRule (std::string rule)
 
+virtual void validate ()=0
 
+void set_added ()
 
+bool is_added ()
 
+std::unique_ptr< BaseRuleupgrade ()
 
+virtual void handle (request &, response &, const routing_params &)=0
 
+virtual void handle_upgrade (const request &, response &res, SocketAdaptor &&)
 
+virtual void handle_upgrade (const request &, response &res, SSLAdaptor &&)
 
+uint32_t get_methods ()
 
+template<typename F >
void foreach_method (F f)
 
+const std::string & rule ()
 
+ + + +

+Public Attributes

+std::string custom_templates_base
 
+ + + + + + + + + + + + + +

+Protected Attributes

+uint32_t methods_ {1 << static_cast<int>(HTTPMethod::Get)}
 
+std::string rule_
 
+std::string name_
 
+bool added_ {false}
 
+std::unique_ptr< BaseRulerule_to_upgrade_
 
+detail::middleware_indices mw_indices_
 
+ + + + + + + + +

+Friends

+class Router
 
+class Blueprint
 
+template<typename T >
struct RuleParameterTraits
 
+

Detailed Description

+

A base class for all rules.

+

Used to provide a common interface for code dealing with different types of rules.
+ A Rule provides a URL, allowed HTTP methods, and handlers.

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_base_rule.js b/1.2/reference/classcrow_1_1_base_rule.js new file mode 100644 index 000000000..e15729767 --- /dev/null +++ b/1.2/reference/classcrow_1_1_base_rule.js @@ -0,0 +1,25 @@ +var classcrow_1_1_base_rule = +[ + [ "BaseRule", "classcrow_1_1_base_rule.html#ada4c61f94eb32ebbb5d553cacbc83013", null ], + [ "~BaseRule", "classcrow_1_1_base_rule.html#a270efe3d144ed2cc638e78758d08b0d8", null ], + [ "foreach_method", "classcrow_1_1_base_rule.html#adea69ae04c498740b73408455197d6a0", null ], + [ "get_methods", "classcrow_1_1_base_rule.html#aba0284ef74a04b9c2401b3a5022f57a6", null ], + [ "handle", "classcrow_1_1_base_rule.html#a0bdeac0dadf0aba8ae19b579e1e615ab", null ], + [ "handle_upgrade", "classcrow_1_1_base_rule.html#acf37339742cfca68b60b9d872382a43d", null ], + [ "handle_upgrade", "classcrow_1_1_base_rule.html#aa26880971650d1333a67ddb6499a4083", null ], + [ "is_added", "classcrow_1_1_base_rule.html#adbb7c2c6d0c750d83168d051c7b52557", null ], + [ "rule", "classcrow_1_1_base_rule.html#ad0e992fd5d9ac9aaf33f7f5ac63c236c", null ], + [ "set_added", "classcrow_1_1_base_rule.html#a6505ff5bab4172129fbc5e8da646b804", null ], + [ "upgrade", "classcrow_1_1_base_rule.html#a9f71a6cab50c4ff480785c4be86d596e", null ], + [ "validate", "classcrow_1_1_base_rule.html#a895d85332340788206cee0b1555ac8c2", null ], + [ "Blueprint", "classcrow_1_1_base_rule.html#a4aa8d706eb7790b068edf67463b3846c", null ], + [ "Router", "classcrow_1_1_base_rule.html#ad1fd3424328f664cd049fe429e0e3dc6", null ], + [ "RuleParameterTraits", "classcrow_1_1_base_rule.html#ae4e239e90000a93c0a1e16dc4cbf8b41", null ], + [ "added_", "classcrow_1_1_base_rule.html#a27fe4fb034003fa9092c8975ecffd838", null ], + [ "custom_templates_base", "classcrow_1_1_base_rule.html#a864205b350008d9c4d8092797acbe4e5", null ], + [ "methods_", "classcrow_1_1_base_rule.html#a997e9942d597fe133df84c94558c1e13", null ], + [ "mw_indices_", "classcrow_1_1_base_rule.html#acd5207b9a30813fcb344ae97bdcdeb72", null ], + [ "name_", "classcrow_1_1_base_rule.html#a34d579887fac170e179e9e69eac3d771", null ], + [ "rule_", "classcrow_1_1_base_rule.html#a39f73fef34a8ff67907d96ef9c92b35a", null ], + [ "rule_to_upgrade_", "classcrow_1_1_base_rule.html#aa08be2b793fe80d462f71c064a9949b8", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_base_rule.png b/1.2/reference/classcrow_1_1_base_rule.png new file mode 100644 index 000000000..353b2f2e0 Binary files /dev/null and b/1.2/reference/classcrow_1_1_base_rule.png differ diff --git a/1.2/reference/classcrow_1_1_blueprint-members.html b/1.2/reference/classcrow_1_1_blueprint-members.html new file mode 100644 index 000000000..224a4b494 --- /dev/null +++ b/1.2/reference/classcrow_1_1_blueprint-members.html @@ -0,0 +1,137 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::Blueprint Member List
+
+
+ +

This is the complete list of members for crow::Blueprint, including all inherited members.

+ + + + + + + + + + + + + + + + + + + +
Blueprint(const std::string &prefix) (defined in crow::Blueprint)crow::Blueprintinline
Blueprint(const std::string &prefix, const std::string &static_dir) (defined in crow::Blueprint)crow::Blueprintinline
Blueprint(const std::string &prefix, const std::string &static_dir, const std::string &templates_dir) (defined in crow::Blueprint)crow::Blueprintinline
Blueprint(Blueprint &&value) (defined in crow::Blueprint)crow::Blueprintinline
catchall_rule() (defined in crow::Blueprint)crow::Blueprintinline
is_added() (defined in crow::Blueprint)crow::Blueprintinline
middlewares() (defined in crow::Blueprint)crow::Blueprintinline
new_rule_dynamic(const std::string &rule) (defined in crow::Blueprint)crow::Blueprintinline
new_rule_tagged(const std::string &rule) (defined in crow::Blueprint)crow::Blueprintinline
operator!=(const Blueprint &value) (defined in crow::Blueprint)crow::Blueprintinline
operator=(const Blueprint &value)=delete (defined in crow::Blueprint)crow::Blueprint
operator=(Blueprint &&value) noexcept (defined in crow::Blueprint)crow::Blueprintinline
operator==(const Blueprint &value) (defined in crow::Blueprint)crow::Blueprintinline
prefix() const (defined in crow::Blueprint)crow::Blueprintinline
register_blueprint(Blueprint &blueprint) (defined in crow::Blueprint)crow::Blueprintinline
Router (defined in crow::Blueprint)crow::Blueprintfriend
set_added() (defined in crow::Blueprint)crow::Blueprintinline
static_dir() const (defined in crow::Blueprint)crow::Blueprintinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_blueprint.html b/1.2/reference/classcrow_1_1_blueprint.html new file mode 100644 index 000000000..076911b2c --- /dev/null +++ b/1.2/reference/classcrow_1_1_blueprint.html @@ -0,0 +1,195 @@ + + + + + + + + Crow: crow::Blueprint Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::Blueprint Class Reference
+
+
+ +

A blueprint can be considered a smaller section of a Crow app, specifically where the router is conecerned. + More...

+ +

#include <routing.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

Blueprint (const std::string &prefix)
 
Blueprint (const std::string &prefix, const std::string &static_dir)
 
Blueprint (const std::string &prefix, const std::string &static_dir, const std::string &templates_dir)
 
Blueprint (Blueprint &&value)
 
+Blueprintoperator= (const Blueprint &value)=delete
 
+Blueprintoperator= (Blueprint &&value) noexcept
 
+bool operator== (const Blueprint &value)
 
+bool operator!= (const Blueprint &value)
 
+std::string prefix () const
 
+std::string static_dir () const
 
+void set_added ()
 
+bool is_added ()
 
+DynamicRulenew_rule_dynamic (const std::string &rule)
 
+template<uint64_t N>
black_magic::arguments< N >::type::template rebind< TaggedRule > & new_rule_tagged (const std::string &rule)
 
+void register_blueprint (Blueprint &blueprint)
 
+CatchallRulecatchall_rule ()
 
+template<typename App , typename... Middlewares>
void middlewares ()
 
+ + + +

+Friends

+class Router
 
+

Detailed Description

+

A blueprint can be considered a smaller section of a Crow app, specifically where the router is conecerned.

+

You can use blueprints to assign a common prefix to rules' prefix, set custom static and template folders, and set a custom catchall route. You can also assign nest blueprints for maximum Compartmentalization.

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_blueprint.js b/1.2/reference/classcrow_1_1_blueprint.js new file mode 100644 index 000000000..f32a8f5af --- /dev/null +++ b/1.2/reference/classcrow_1_1_blueprint.js @@ -0,0 +1,21 @@ +var classcrow_1_1_blueprint = +[ + [ "Blueprint", "classcrow_1_1_blueprint.html#a6938b2b0a1269f016e924f9df6c944b3", null ], + [ "Blueprint", "classcrow_1_1_blueprint.html#a41f0515e11ecbb9729a2953ee51beaf0", null ], + [ "Blueprint", "classcrow_1_1_blueprint.html#a1eddf3e4a0330754e43e06ec8ac99467", null ], + [ "Blueprint", "classcrow_1_1_blueprint.html#a0af074f28f07310e64b2b3561162870e", null ], + [ "catchall_rule", "classcrow_1_1_blueprint.html#a51c3bddee7c7065165fdc80141dbce3d", null ], + [ "is_added", "classcrow_1_1_blueprint.html#a95b5a0080c263adb3d7851f78d6723a9", null ], + [ "middlewares", "classcrow_1_1_blueprint.html#a3c3880497e8d6d8fbac6719aea1525d5", null ], + [ "new_rule_dynamic", "classcrow_1_1_blueprint.html#a69a801211cc2a2db099b115867d657ca", null ], + [ "new_rule_tagged", "classcrow_1_1_blueprint.html#a8b7632256baf408ab8cdc84699a21e0b", null ], + [ "operator!=", "classcrow_1_1_blueprint.html#a2c64b156ddd9feb9bc50ec796054c0ff", null ], + [ "operator=", "classcrow_1_1_blueprint.html#a8060c88347e3e09eeec4e3c4b3940592", null ], + [ "operator=", "classcrow_1_1_blueprint.html#a94d355dbfbea87a0764009e60c310048", null ], + [ "operator==", "classcrow_1_1_blueprint.html#a12b93ae342e7d5f2db0b86774a3b0ff5", null ], + [ "prefix", "classcrow_1_1_blueprint.html#a64c98b3f3c17650e2bd01491754240b8", null ], + [ "register_blueprint", "classcrow_1_1_blueprint.html#addfbb64ccb9b8841d82e1dad9c454acc", null ], + [ "set_added", "classcrow_1_1_blueprint.html#a757176326f248c514ec8c7ea1eb11a2f", null ], + [ "static_dir", "classcrow_1_1_blueprint.html#a9aa533304758b1461734b49f8273e7e4", null ], + [ "Router", "classcrow_1_1_blueprint.html#ad1fd3424328f664cd049fe429e0e3dc6", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_catchall_rule-members.html b/1.2/reference/classcrow_1_1_catchall_rule-members.html new file mode 100644 index 000000000..3fcdc9e57 --- /dev/null +++ b/1.2/reference/classcrow_1_1_catchall_rule-members.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::CatchallRule Member List
+
+
+ +

This is the complete list of members for crow::CatchallRule, including all inherited members.

+ + + +
has_handler() (defined in crow::CatchallRule)crow::CatchallRuleinline
Router (defined in crow::CatchallRule)crow::CatchallRulefriend
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_catchall_rule.html b/1.2/reference/classcrow_1_1_catchall_rule.html new file mode 100644 index 000000000..0c25290e6 --- /dev/null +++ b/1.2/reference/classcrow_1_1_catchall_rule.html @@ -0,0 +1,137 @@ + + + + + + + + Crow: crow::CatchallRule Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::CatchallRule Class Reference
+
+
+ + + + +

+Public Member Functions

+bool has_handler ()
 
+ + + +

+Friends

+class Router
 
+
The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_catchall_rule.js b/1.2/reference/classcrow_1_1_catchall_rule.js new file mode 100644 index 000000000..ff04faab3 --- /dev/null +++ b/1.2/reference/classcrow_1_1_catchall_rule.js @@ -0,0 +1,5 @@ +var classcrow_1_1_catchall_rule = +[ + [ "has_handler", "classcrow_1_1_catchall_rule.html#a3a05d5d9f931ba32f96f058bfe6c3de2", null ], + [ "Router", "classcrow_1_1_catchall_rule.html#ad1fd3424328f664cd049fe429e0e3dc6", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_cerr_log_handler-members.html b/1.2/reference/classcrow_1_1_cerr_log_handler-members.html new file mode 100644 index 000000000..394dcbd7c --- /dev/null +++ b/1.2/reference/classcrow_1_1_cerr_log_handler-members.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::CerrLogHandler Member List
+
+
+ +

This is the complete list of members for crow::CerrLogHandler, including all inherited members.

+ + + +
log(std::string message, LogLevel level) override (defined in crow::CerrLogHandler)crow::CerrLogHandlerinlinevirtual
~ILogHandler()=default (defined in crow::ILogHandler)crow::ILogHandlervirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_cerr_log_handler.html b/1.2/reference/classcrow_1_1_cerr_log_handler.html new file mode 100644 index 000000000..e0382a8bd --- /dev/null +++ b/1.2/reference/classcrow_1_1_cerr_log_handler.html @@ -0,0 +1,139 @@ + + + + + + + + Crow: crow::CerrLogHandler Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::CerrLogHandler Class Reference
+
+
+
+Inheritance diagram for crow::CerrLogHandler:
+
+
+ + +crow::ILogHandler + +
+ + + + +

+Public Member Functions

+void log (std::string message, LogLevel level) override
 
+
The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_cerr_log_handler.js b/1.2/reference/classcrow_1_1_cerr_log_handler.js new file mode 100644 index 000000000..088756e21 --- /dev/null +++ b/1.2/reference/classcrow_1_1_cerr_log_handler.js @@ -0,0 +1,4 @@ +var classcrow_1_1_cerr_log_handler = +[ + [ "log", "classcrow_1_1_cerr_log_handler.html#a8c0f59589facc283b5cd99ead9a1d2c4", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_cerr_log_handler.png b/1.2/reference/classcrow_1_1_cerr_log_handler.png new file mode 100644 index 000000000..d40bc8ac3 Binary files /dev/null and b/1.2/reference/classcrow_1_1_cerr_log_handler.png differ diff --git a/1.2/reference/classcrow_1_1_connection-members.html b/1.2/reference/classcrow_1_1_connection-members.html new file mode 100644 index 000000000..10d218470 --- /dev/null +++ b/1.2/reference/classcrow_1_1_connection-members.html @@ -0,0 +1,128 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::Connection< Adaptor, Handler, Middlewares > Member List
+
+
+ +

This is the complete list of members for crow::Connection< Adaptor, Handler, Middlewares >, including all inherited members.

+ + + + + + + + + + +
complete_request()crow::Connection< Adaptor, Handler, Middlewares >inline
Connection(asio::io_service &io_service, Handler *handler, const std::string &server_name, std::tuple< Middlewares... > *middlewares, std::function< std::string()> &get_cached_date_str_f, detail::task_timer &task_timer, typename Adaptor::context *adaptor_ctx_, std::atomic< unsigned int > &queue_length) (defined in crow::Connection< Adaptor, Handler, Middlewares >)crow::Connection< Adaptor, Handler, Middlewares >inline
crow::response (defined in crow::Connection< Adaptor, Handler, Middlewares >)crow::Connection< Adaptor, Handler, Middlewares >friend
handle() (defined in crow::Connection< Adaptor, Handler, Middlewares >)crow::Connection< Adaptor, Handler, Middlewares >inline
handle_header() (defined in crow::Connection< Adaptor, Handler, Middlewares >)crow::Connection< Adaptor, Handler, Middlewares >inline
handle_url() (defined in crow::Connection< Adaptor, Handler, Middlewares >)crow::Connection< Adaptor, Handler, Middlewares >inline
socket()crow::Connection< Adaptor, Handler, Middlewares >inline
start() (defined in crow::Connection< Adaptor, Handler, Middlewares >)crow::Connection< Adaptor, Handler, Middlewares >inline
~Connection() (defined in crow::Connection< Adaptor, Handler, Middlewares >)crow::Connection< Adaptor, Handler, Middlewares >inline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_connection.html b/1.2/reference/classcrow_1_1_connection.html new file mode 100644 index 000000000..5eae109e5 --- /dev/null +++ b/1.2/reference/classcrow_1_1_connection.html @@ -0,0 +1,173 @@ + + + + + + + + Crow: crow::Connection< Adaptor, Handler, Middlewares > Class Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::Connection< Adaptor, Handler, Middlewares > Class Template Reference
+
+
+ +

An HTTP connection. + More...

+ +

#include <http_connection.h>

+
+Inheritance diagram for crow::Connection< Adaptor, Handler, Middlewares >:
+
+
+ +
+ + + + + + + + + + + + + + + + + + +

+Public Member Functions

Connection (asio::io_service &io_service, Handler *handler, const std::string &server_name, std::tuple< Middlewares... > *middlewares, std::function< std::string()> &get_cached_date_str_f, detail::task_timer &task_timer, typename Adaptor::context *adaptor_ctx_, std::atomic< unsigned int > &queue_length)
 
+decltype(std::declval< Adaptor >().raw_socket()) & socket ()
 The TCP socket on top of which the connection is established.
 
+void start ()
 
+void handle_url ()
 
+void handle_header ()
 
+void handle ()
 
+void complete_request ()
 Call the after handle middleware and send the write the response to the connection.
 
+ + + +

+Friends

+struct crow::response
 
+

Detailed Description

+

template<typename Adaptor, typename Handler, typename... Middlewares>
+class crow::Connection< Adaptor, Handler, Middlewares >

+ +

An HTTP connection.

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_connection.js b/1.2/reference/classcrow_1_1_connection.js new file mode 100644 index 000000000..2df0d890c --- /dev/null +++ b/1.2/reference/classcrow_1_1_connection.js @@ -0,0 +1,12 @@ +var classcrow_1_1_connection = +[ + [ "Connection", "classcrow_1_1_connection.html#ad83a6948c16db75e51dcf7514f298983", null ], + [ "~Connection", "classcrow_1_1_connection.html#a4800edf5f2600ecdefd7d792d237b945", null ], + [ "complete_request", "classcrow_1_1_connection.html#aa40019a3731cc55174401e3b31602524", null ], + [ "handle", "classcrow_1_1_connection.html#ac347b6e80cfbc071579781062c78e667", null ], + [ "handle_header", "classcrow_1_1_connection.html#adde7a01b5ad446b0f7b1fb6fa6d3c23b", null ], + [ "handle_url", "classcrow_1_1_connection.html#aeca557cd8422769c3b819343a7ed012d", null ], + [ "socket", "classcrow_1_1_connection.html#adb5878dd700c30dae10f3fa8d06ecbab", null ], + [ "start", "classcrow_1_1_connection.html#a00e6802466a18fd967ce065522844e2f", null ], + [ "crow::response", "classcrow_1_1_connection.html#a6fdaf752fa7f9477577ad34e5a2b1506", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_connection.png b/1.2/reference/classcrow_1_1_connection.png new file mode 100644 index 000000000..6725d8cea Binary files /dev/null and b/1.2/reference/classcrow_1_1_connection.png differ diff --git a/1.2/reference/classcrow_1_1_crow-members.html b/1.2/reference/classcrow_1_1_crow-members.html new file mode 100644 index 000000000..bc059e349 --- /dev/null +++ b/1.2/reference/classcrow_1_1_crow-members.html @@ -0,0 +1,174 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::Crow< Middlewares > Member List
+
+
+ +

This is the complete list of members for crow::Crow< Middlewares >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
add_blueprint()crow::Crow< Middlewares >inline
add_static_dir()crow::Crow< Middlewares >inline
add_websocket(crow::websocket::connection *conn) (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
bindaddr(std::string bindaddr)crow::Crow< Middlewares >inline
bindaddr()crow::Crow< Middlewares >inline
catchall_route()crow::Crow< Middlewares >inline
compression_algorithm() (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
compression_used() const (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
concurrency(std::uint16_t concurrency)crow::Crow< Middlewares >inline
concurrency()crow::Crow< Middlewares >inline
context_t typedef (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >
Crow() (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
Crow(Ts &&... ts)crow::Crow< Middlewares >inline
debug_print()crow::Crow< Middlewares >inline
exception_handler(Func &&f)crow::Crow< Middlewares >inline
exception_handler() (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
get_context(const request &req) (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
get_middleware() (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
handle(request &req, response &res, std::unique_ptr< routing_handle_result > &found)crow::Crow< Middlewares >inline
handle_full(request &req, response &res)crow::Crow< Middlewares >inline
handle_initial(request &req, response &res)crow::Crow< Middlewares >inline
handle_upgrade(const request &req, response &res, Adaptor &&adaptor)crow::Crow< Middlewares >inline
loglevel(LogLevel level)crow::Crow< Middlewares >inline
multithreaded()crow::Crow< Middlewares >inline
mw_container_t typedef (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >
port(std::uint16_t port)crow::Crow< Middlewares >inline
port()crow::Crow< Middlewares >inline
register_blueprint(Blueprint &blueprint) (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
remove_websocket(crow::websocket::connection *conn) (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
route(const std::string &rule) -> typename std::result_of< decltype(&Router::new_rule_tagged< Tag >)(Router, const std::string &)>::typecrow::Crow< Middlewares >inline
route_dynamic(const std::string &rule)crow::Crow< Middlewares >inline
run()crow::Crow< Middlewares >inline
run_async()crow::Crow< Middlewares >inline
self_t typedefcrow::Crow< Middlewares >
server_name(std::string server_name)crow::Crow< Middlewares >inline
server_t typedefcrow::Crow< Middlewares >
signal_add(int signal_number) (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
signal_clear() (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
signals() (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
ssl(asio::ssl::context &&ctx) (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
ssl_chainfile(const std::string &crt_filename, const std::string &key_filename)crow::Crow< Middlewares >inline
ssl_file(const std::string &crt_filename, const std::string &key_filename)crow::Crow< Middlewares >inline
ssl_file(const std::string &pem_filename)crow::Crow< Middlewares >inline
ssl_server_t typedefcrow::Crow< Middlewares >
ssl_used() const (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
stop()crow::Crow< Middlewares >inline
stream_threshold(size_t threshold)crow::Crow< Middlewares >inline
stream_threshold()crow::Crow< Middlewares >inline
tick(Duration d, Func f)crow::Crow< Middlewares >inline
timeout(std::uint8_t timeout)crow::Crow< Middlewares >inline
use_compression(compression::algorithm algorithm) (defined in crow::Crow< Middlewares >)crow::Crow< Middlewares >inline
validate()crow::Crow< Middlewares >inline
wait_for_server_start()crow::Crow< Middlewares >inline
websocket_max_payload(uint64_t max_payload)crow::Crow< Middlewares >inline
websocket_max_payload()crow::Crow< Middlewares >inline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_crow.html b/1.2/reference/classcrow_1_1_crow.html new file mode 100644 index 000000000..4d868bf74 --- /dev/null +++ b/1.2/reference/classcrow_1_1_crow.html @@ -0,0 +1,525 @@ + + + + + + + + Crow: crow::Crow< Middlewares > Class Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::Crow< Middlewares > Class Template Reference
+
+
+ +

The main server application class. + More...

+ +

#include <app.h>

+ + + + + + + + + + + + + + + +

+Public Types

+using self_t = Crow
 This is the crow application.
 
+using server_t = Server< Crow, SocketAdaptor, Middlewares... >
 The HTTP server.
 
+using ssl_server_t = Server< Crow, SSLAdaptor, Middlewares... >
 An HTTP server that runs on SSL with an SSLAdaptor.
 
+using context_t = detail::context< Middlewares... >
 
+using mw_container_t = std::tuple< Middlewares... >
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

+template<typename... Ts>
 Crow (Ts &&... ts)
 Construct Crow with a subset of middleware.
 
template<typename Adaptor >
void handle_upgrade (const request &req, response &res, Adaptor &&adaptor)
 Process an Upgrade request. More...
 
+std::unique_ptr< routing_handle_resulthandle_initial (request &req, response &res)
 Process only the method and URL of a request and provide a route (or an error response)
 
+void handle (request &req, response &res, std::unique_ptr< routing_handle_result > &found)
 Process the fully parsed request and generate a response for it.
 
+void handle_full (request &req, response &res)
 Process a fully parsed request from start to finish (primarily used for debugging)
 
+DynamicRuleroute_dynamic (const std::string &rule)
 Create a dynamic route using a rule (Use CROW_ROUTE instead)
 
+template<uint64_t Tag>
auto route (const std::string &rule) -> typename std::result_of< decltype(&Router::new_rule_tagged< Tag >)(Router, const std::string &)>::type
 Create a route using a rule (Use CROW_ROUTE instead)
 
+CatchallRulecatchall_route ()
 Create a route for any requests without a proper route (Use CROW_CATCHALL_ROUTE instead)
 
+self_twebsocket_max_payload (uint64_t max_payload)
 Set the default max payload size for websockets.
 
+uint64_t websocket_max_payload ()
 Get the default max payload size for websockets.
 
+self_tsignal_clear ()
 
+self_tsignal_add (int signal_number)
 
+std::vector< int > signals ()
 
+self_tport (std::uint16_t port)
 Set the port that Crow will handle requests on.
 
+std::uint16_t port ()
 Get the port that Crow will handle requests on.
 
+self_ttimeout (std::uint8_t timeout)
 Set the connection timeout in seconds (default is 5)
 
+self_tserver_name (std::string server_name)
 Set the server name.
 
+self_tbindaddr (std::string bindaddr)
 The IP address that Crow will handle requests on (default is 0.0.0.0)
 
+std::string bindaddr ()
 Get the address that Crow will handle requests on.
 
+self_tmultithreaded ()
 Run the server on multiple threads using all available threads.
 
+self_tconcurrency (std::uint16_t concurrency)
 Run the server on multiple threads using a specific number.
 
+std::uint16_t concurrency ()
 Get the number of threads that server is using.
 
self_tloglevel (LogLevel level)
 Set the server's log level. More...
 
self_tstream_threshold (size_t threshold)
 Set the response body size (in bytes) beyond which Crow automatically streams responses (Default is 1MiB) More...
 
+size_t & stream_threshold ()
 Get the response body size (in bytes) beyond which Crow automatically streams responses.
 
+self_tregister_blueprint (Blueprint &blueprint)
 
template<typename Func >
self_texception_handler (Func &&f)
 Set the function to call to handle uncaught exceptions generated in routes (Default generates error 500). More...
 
+std::function< void(crow::response &)> & exception_handler ()
 
+template<typename Duration , typename Func >
self_ttick (Duration d, Func f)
 Set a custom duration and function to run on every tick.
 
+self_tuse_compression (compression::algorithm algorithm)
 
+compression::algorithm compression_algorithm ()
 
+bool compression_used () const
 
+void add_blueprint ()
 Apply blueprints.
 
+void add_static_dir ()
 Go through the rules, upgrade them if possible, and add them to the list of rules.
 
+void validate ()
 A wrapper for validate() in the router.
 
+void run ()
 Run the server.
 
std::future< void > run_async ()
 Non-blocking version of run() More...
 
+void stop ()
 Stop the server.
 
+void add_websocket (crow::websocket::connection *conn)
 
+void remove_websocket (crow::websocket::connection *conn)
 
+void debug_print ()
 Print the routing paths defined for each HTTP method.
 
+self_tssl_file (const std::string &crt_filename, const std::string &key_filename)
 Use certificate and key files for SSL.
 
+self_tssl_file (const std::string &pem_filename)
 Use .pem file for SSL.
 
+self_tssl_chainfile (const std::string &crt_filename, const std::string &key_filename)
 Use certificate chain and key files for SSL.
 
+self_tssl (asio::ssl::context &&ctx)
 
+bool ssl_used () const
 
+template<typename T >
T::context & get_context (const request &req)
 
+template<typename T >
T & get_middleware ()
 
+void wait_for_server_start ()
 Wait until the server has properly started.
 
+

Detailed Description

+

template<typename... Middlewares>
+class crow::Crow< Middlewares >

+ +

The main server application class.

+

Use crow::SimpleApp or crow::App<Middleware1, Middleware2, etc...> instead of directly instantiate this class.

+

Member Function Documentation

+ +

◆ exception_handler()

+ +
+
+
+template<typename... Middlewares>
+
+template<typename Func >
+ + + + + +
+ + + + + + + + +
self_t& crow::Crow< Middlewares >::exception_handler (Func && f)
+
+inline
+
+ +

Set the function to call to handle uncaught exceptions generated in routes (Default generates error 500).

+

The function must have the following signature: void(crow::response&). It must set the response passed in argument to the function, which will be sent back to the client. See Router::default_exception_handler() for the default implementation.

+ +
+
+ +

◆ handle_upgrade()

+ +
+
+
+template<typename... Middlewares>
+
+template<typename Adaptor >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
void crow::Crow< Middlewares >::handle_upgrade (const requestreq,
responseres,
Adaptor && adaptor 
)
+
+inline
+
+ +

Process an Upgrade request.

+

Currently used to upgrade an HTTP connection to a WebSocket connection

+ +
+
+ +

◆ loglevel()

+ +
+
+
+template<typename... Middlewares>
+ + + + + +
+ + + + + + + + +
self_t& crow::Crow< Middlewares >::loglevel (LogLevel level)
+
+inline
+
+ +

Set the server's log level.

+

Possible values are:

    +
  • crow::LogLevel::Debug (0)
  • +
  • crow::LogLevel::Info (1)
  • +
  • crow::LogLevel::Warning (2)
  • +
  • crow::LogLevel::Error (3)
  • +
  • crow::LogLevel::Critical (4)
  • +
+ +
+
+ +

◆ run_async()

+ +
+
+
+template<typename... Middlewares>
+ + + + + +
+ + + + + + + +
std::future<void> crow::Crow< Middlewares >::run_async ()
+
+inline
+
+ +

Non-blocking version of run()

+

The output from this method needs to be saved into a variable! Otherwise the call will be made on the same thread.

+ +
+
+ +

◆ stream_threshold()

+ +
+
+
+template<typename... Middlewares>
+ + + + + +
+ + + + + + + + +
self_t& crow::Crow< Middlewares >::stream_threshold (size_t threshold)
+
+inline
+
+ +

Set the response body size (in bytes) beyond which Crow automatically streams responses (Default is 1MiB)

+

Any streamed response is unaffected by Crow's timer, and therefore won't timeout before a response is fully sent.

+ +
+
+
The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_crow.js b/1.2/reference/classcrow_1_1_crow.js new file mode 100644 index 000000000..728f68b81 --- /dev/null +++ b/1.2/reference/classcrow_1_1_crow.js @@ -0,0 +1,58 @@ +var classcrow_1_1_crow = +[ + [ "context_t", "classcrow_1_1_crow.html#a980ca09ad971f8915a3575d9a94fe78c", null ], + [ "mw_container_t", "classcrow_1_1_crow.html#aa78aacbc64349155aab3f81d32715189", null ], + [ "self_t", "classcrow_1_1_crow.html#a5b0a203a6f9070ea8010227dcdbcec60", null ], + [ "server_t", "classcrow_1_1_crow.html#a5df810d2619e31c2f024cc4e45898997", null ], + [ "ssl_server_t", "classcrow_1_1_crow.html#aac04f81d0bc897267d092bb8af1513d4", null ], + [ "Crow", "classcrow_1_1_crow.html#a7a6ce30b00d6d2beb901ffbb3160c137", null ], + [ "Crow", "classcrow_1_1_crow.html#abb69a7bf5d4a791a398c838d37086d94", null ], + [ "add_blueprint", "classcrow_1_1_crow.html#af0d01b97da7d4d20844a80fd31b74f46", null ], + [ "add_static_dir", "classcrow_1_1_crow.html#a3cbe89120e47d2bd3d05376b9129adfa", null ], + [ "add_websocket", "classcrow_1_1_crow.html#ad38f39dc7ba97b9f298390565a88125a", null ], + [ "bindaddr", "classcrow_1_1_crow.html#a8c816534804e7bd351ca692005bf3343", null ], + [ "bindaddr", "classcrow_1_1_crow.html#a75777f82b6519c86d71446eb9285d774", null ], + [ "catchall_route", "classcrow_1_1_crow.html#ab1beefb0c6fc3c534160ba3bbc615069", null ], + [ "compression_algorithm", "classcrow_1_1_crow.html#a261b73d1f1f463856cceee2c589cbbf4", null ], + [ "compression_used", "classcrow_1_1_crow.html#a022f4943770af09b032552e62715ee7e", null ], + [ "concurrency", "classcrow_1_1_crow.html#abd824d73fdd02ba810b8dd37e2900240", null ], + [ "concurrency", "classcrow_1_1_crow.html#a41686e6025705c1ab379b5ec71bbf983", null ], + [ "debug_print", "classcrow_1_1_crow.html#a839c1e6f82d577308eb6f0d4948a4fbb", null ], + [ "exception_handler", "classcrow_1_1_crow.html#a46c77db2adcad57e95b807e6f58fc006", null ], + [ "exception_handler", "classcrow_1_1_crow.html#a872d39321015ac4f48ec8a6659dda99b", null ], + [ "get_context", "classcrow_1_1_crow.html#ab9f401a95ab8fdc6ec65d542899954cc", null ], + [ "get_middleware", "classcrow_1_1_crow.html#a416e872b703c27154845aca516d0a417", null ], + [ "handle", "classcrow_1_1_crow.html#a866cb219bb77c19326f39f431424e1c7", null ], + [ "handle_full", "classcrow_1_1_crow.html#accf00be55c273297b758fa243f107018", null ], + [ "handle_initial", "classcrow_1_1_crow.html#a761ebd8c33ae35a3c61c7a160ad40789", null ], + [ "handle_upgrade", "classcrow_1_1_crow.html#a6e435bf5275735effd32647772bdbd04", null ], + [ "loglevel", "classcrow_1_1_crow.html#a7b6c225d3bba772eeadad89ebde68d21", null ], + [ "multithreaded", "classcrow_1_1_crow.html#a0149b20b7f6c0123292286f54638d456", null ], + [ "port", "classcrow_1_1_crow.html#a87d0e10ed791c6847d8b7dfff2369aae", null ], + [ "port", "classcrow_1_1_crow.html#a365f9c95fc2bd8bb583967f499c1f4a1", null ], + [ "register_blueprint", "classcrow_1_1_crow.html#a7d16da8824a6d6c376395f4bfa73430e", null ], + [ "remove_websocket", "classcrow_1_1_crow.html#a5305aba0aea70aa0e283c4ff8d78bbbf", null ], + [ "route", "classcrow_1_1_crow.html#a5e1e54d49ff3015fd08f545b574ab44f", null ], + [ "route_dynamic", "classcrow_1_1_crow.html#a0822a573ed653c3218f06c819a773ec2", null ], + [ "run", "classcrow_1_1_crow.html#a193d8b03f717234a841cd92f72c6b4b5", null ], + [ "run_async", "classcrow_1_1_crow.html#aac4f72d944fb35caaf2d82cd21287269", null ], + [ "server_name", "classcrow_1_1_crow.html#ae0e400a1757bd68f716b82753a5a1a73", null ], + [ "signal_add", "classcrow_1_1_crow.html#acf706e62049ea737aec5a79e61e1fe3f", null ], + [ "signal_clear", "classcrow_1_1_crow.html#a11832be23c0a0296b5ed2023361f6205", null ], + [ "signals", "classcrow_1_1_crow.html#a41804939e4051bee424689fe4fb80baa", null ], + [ "ssl", "classcrow_1_1_crow.html#ad796f0d82060097a6cf776a3f1508b8d", null ], + [ "ssl_chainfile", "classcrow_1_1_crow.html#ade6bf7e56805c1112532807581293448", null ], + [ "ssl_file", "classcrow_1_1_crow.html#a987e909347f0563f7b3dd97bbe271cea", null ], + [ "ssl_file", "classcrow_1_1_crow.html#a3e5aa337025914852fcbfd1aebbd3241", null ], + [ "ssl_used", "classcrow_1_1_crow.html#ac804a73fa33d77a281c4609727ec1676", null ], + [ "stop", "classcrow_1_1_crow.html#a0266672657128919ab9a067d93f3868f", null ], + [ "stream_threshold", "classcrow_1_1_crow.html#a0a7b45c935e58d199eb1bcba86003232", null ], + [ "stream_threshold", "classcrow_1_1_crow.html#ae92390d22f6fc99987c41a617be71d64", null ], + [ "tick", "classcrow_1_1_crow.html#a068042431b0be5911ee1689a285f4693", null ], + [ "timeout", "classcrow_1_1_crow.html#a47ed9a118820f6e6ba0b2bc37f0997fb", null ], + [ "use_compression", "classcrow_1_1_crow.html#ae53a1544edf04f08eeb2e35f01dc25d3", null ], + [ "validate", "classcrow_1_1_crow.html#ab9a22c981e0afec0d55ee234683a6d38", null ], + [ "wait_for_server_start", "classcrow_1_1_crow.html#a5e39821ccc9cbf8c6400fd86fc406c21", null ], + [ "websocket_max_payload", "classcrow_1_1_crow.html#a391a488c01ce53c0ccfd502c7ad15640", null ], + [ "websocket_max_payload", "classcrow_1_1_crow.html#a30d9cbcaa6aa3c3e44a8a3c4479fd7cf", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_dynamic_rule-members.html b/1.2/reference/classcrow_1_1_dynamic_rule-members.html new file mode 100644 index 000000000..e27faa2de --- /dev/null +++ b/1.2/reference/classcrow_1_1_dynamic_rule-members.html @@ -0,0 +1,148 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::DynamicRule Member List
+
+
+ +

This is the complete list of members for crow::DynamicRule, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
added_ (defined in crow::BaseRule)crow::BaseRuleprotected
BaseRule(std::string rule) (defined in crow::BaseRule)crow::BaseRuleinline
custom_templates_base (defined in crow::BaseRule)crow::BaseRule
DynamicRule(std::string rule) (defined in crow::DynamicRule)crow::DynamicRuleinline
foreach_method(F f) (defined in crow::BaseRule)crow::BaseRuleinline
get_methods() (defined in crow::BaseRule)crow::BaseRuleinline
handle(request &req, response &res, const routing_params &params) override (defined in crow::DynamicRule)crow::DynamicRuleinlinevirtual
handle_upgrade(const request &, response &res, SocketAdaptor &&) (defined in crow::BaseRule)crow::BaseRuleinlinevirtual
handle_upgrade(const request &, response &res, SSLAdaptor &&) (defined in crow::BaseRule)crow::BaseRuleinlinevirtual
is_added() (defined in crow::BaseRule)crow::BaseRuleinline
methods(HTTPMethod method) (defined in crow::RuleParameterTraits< DynamicRule >)crow::RuleParameterTraits< DynamicRule >inline
methods(HTTPMethod method, MethodArgs... args_method) (defined in crow::RuleParameterTraits< DynamicRule >)crow::RuleParameterTraits< DynamicRule >inline
methods_ (defined in crow::BaseRule)crow::BaseRuleprotected
middlewares()crow::RuleParameterTraits< DynamicRule >inline
mw_indices_ (defined in crow::BaseRule)crow::BaseRuleprotected
name(std::string name) noexcept (defined in crow::RuleParameterTraits< DynamicRule >)crow::RuleParameterTraits< DynamicRule >inline
name_ (defined in crow::BaseRule)crow::BaseRuleprotected
operator()(Func f) (defined in crow::DynamicRule)crow::DynamicRuleinline
operator()(std::string name, Func &&f) (defined in crow::DynamicRule)crow::DynamicRuleinline
rule() (defined in crow::BaseRule)crow::BaseRuleinline
rule_ (defined in crow::BaseRule)crow::BaseRuleprotected
rule_to_upgrade_ (defined in crow::BaseRule)crow::BaseRuleprotected
self_t typedef (defined in crow::RuleParameterTraits< DynamicRule >)crow::RuleParameterTraits< DynamicRule >
set_added() (defined in crow::BaseRule)crow::BaseRuleinline
upgrade() (defined in crow::BaseRule)crow::BaseRuleinline
validate() override (defined in crow::DynamicRule)crow::DynamicRuleinlinevirtual
websocket(App *app) (defined in crow::RuleParameterTraits< DynamicRule >)crow::RuleParameterTraits< DynamicRule >inline
wrap(Func f, black_magic::seq< Indices... >) (defined in crow::DynamicRule)crow::DynamicRuleinline
~BaseRule() (defined in crow::BaseRule)crow::BaseRuleinlinevirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_dynamic_rule.html b/1.2/reference/classcrow_1_1_dynamic_rule.html new file mode 100644 index 000000000..0ba397b21 --- /dev/null +++ b/1.2/reference/classcrow_1_1_dynamic_rule.html @@ -0,0 +1,241 @@ + + + + + + + + Crow: crow::DynamicRule Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::DynamicRule Class Reference
+
+
+ +

A rule that can change its parameters during runtime. + More...

+ +

#include <routing.h>

+
+Inheritance diagram for crow::DynamicRule:
+
+
+ + +crow::BaseRule +crow::RuleParameterTraits< DynamicRule > + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

DynamicRule (std::string rule)
 
+void validate () override
 
+void handle (request &req, response &res, const routing_params &params) override
 
+template<typename Func >
void operator() (Func f)
 
+template<typename Func , unsigned... Indices>
std::function< void(request &, response &, const routing_params &)> wrap (Func f, black_magic::seq< Indices... >)
 
+template<typename Func >
void operator() (std::string name, Func &&f)
 
- Public Member Functions inherited from crow::BaseRule
BaseRule (std::string rule)
 
+void set_added ()
 
+bool is_added ()
 
+std::unique_ptr< BaseRuleupgrade ()
 
+virtual void handle_upgrade (const request &, response &res, SocketAdaptor &&)
 
+virtual void handle_upgrade (const request &, response &res, SSLAdaptor &&)
 
+uint32_t get_methods ()
 
+template<typename F >
void foreach_method (F f)
 
+const std::string & rule ()
 
- Public Member Functions inherited from crow::RuleParameterTraits< DynamicRule >
+WebSocketRule< App > & websocket (App *app)
 
+self_tname (std::string name) noexcept
 
+self_tmethods (HTTPMethod method)
 
+self_tmethods (HTTPMethod method, MethodArgs... args_method)
 
+self_tmiddlewares ()
 Enable local middleware for this handler.
 
+ + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Public Types inherited from crow::RuleParameterTraits< DynamicRule >
+using self_t = DynamicRule
 
- Public Attributes inherited from crow::BaseRule
+std::string custom_templates_base
 
- Protected Attributes inherited from crow::BaseRule
+uint32_t methods_ {1 << static_cast<int>(HTTPMethod::Get)}
 
+std::string rule_
 
+std::string name_
 
+bool added_ {false}
 
+std::unique_ptr< BaseRulerule_to_upgrade_
 
+detail::middleware_indices mw_indices_
 
+

Detailed Description

+

A rule that can change its parameters during runtime.

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_dynamic_rule.js b/1.2/reference/classcrow_1_1_dynamic_rule.js new file mode 100644 index 000000000..559ecb722 --- /dev/null +++ b/1.2/reference/classcrow_1_1_dynamic_rule.js @@ -0,0 +1,9 @@ +var classcrow_1_1_dynamic_rule = +[ + [ "DynamicRule", "classcrow_1_1_dynamic_rule.html#ae34a9eac492ec9ed8e7c7ef036afcfec", null ], + [ "handle", "classcrow_1_1_dynamic_rule.html#ad15e58c75d76bb1d6120302ef2c36c58", null ], + [ "operator()", "classcrow_1_1_dynamic_rule.html#a482a85c52b9815f5e0715e0840ab7024", null ], + [ "operator()", "classcrow_1_1_dynamic_rule.html#a8c18b9fad80fd47934051f41286a4a9e", null ], + [ "validate", "classcrow_1_1_dynamic_rule.html#ad044e4cacd82591b1d9b1115f0d0bea1", null ], + [ "wrap", "classcrow_1_1_dynamic_rule.html#afeb43c0a479bd8c14ba37e92b49e65ee", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_dynamic_rule.png b/1.2/reference/classcrow_1_1_dynamic_rule.png new file mode 100644 index 000000000..552c49327 Binary files /dev/null and b/1.2/reference/classcrow_1_1_dynamic_rule.png differ diff --git a/1.2/reference/classcrow_1_1_i_log_handler-members.html b/1.2/reference/classcrow_1_1_i_log_handler-members.html new file mode 100644 index 000000000..f03aa0aac --- /dev/null +++ b/1.2/reference/classcrow_1_1_i_log_handler-members.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::ILogHandler Member List
+
+
+ +

This is the complete list of members for crow::ILogHandler, including all inherited members.

+ + + +
log(std::string message, LogLevel level)=0 (defined in crow::ILogHandler)crow::ILogHandlerpure virtual
~ILogHandler()=default (defined in crow::ILogHandler)crow::ILogHandlervirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_i_log_handler.html b/1.2/reference/classcrow_1_1_i_log_handler.html new file mode 100644 index 000000000..40f75e748 --- /dev/null +++ b/1.2/reference/classcrow_1_1_i_log_handler.html @@ -0,0 +1,139 @@ + + + + + + + + Crow: crow::ILogHandler Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::ILogHandler Class Referenceabstract
+
+
+
+Inheritance diagram for crow::ILogHandler:
+
+
+ + +crow::CerrLogHandler + +
+ + + + +

+Public Member Functions

+virtual void log (std::string message, LogLevel level)=0
 
+
The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_i_log_handler.js b/1.2/reference/classcrow_1_1_i_log_handler.js new file mode 100644 index 000000000..4e355f778 --- /dev/null +++ b/1.2/reference/classcrow_1_1_i_log_handler.js @@ -0,0 +1,5 @@ +var classcrow_1_1_i_log_handler = +[ + [ "~ILogHandler", "classcrow_1_1_i_log_handler.html#a86f05e42d2495f90ed63cc8482064c7e", null ], + [ "log", "classcrow_1_1_i_log_handler.html#ae17f05549983c9d7d6aea77cda589f60", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_i_log_handler.png b/1.2/reference/classcrow_1_1_i_log_handler.png new file mode 100644 index 000000000..6fff0d6ef Binary files /dev/null and b/1.2/reference/classcrow_1_1_i_log_handler.png differ diff --git a/1.2/reference/classcrow_1_1_router-members.html b/1.2/reference/classcrow_1_1_router-members.html new file mode 100644 index 000000000..88b4217b8 --- /dev/null +++ b/1.2/reference/classcrow_1_1_router-members.html @@ -0,0 +1,141 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::Router Member List
+
+
+ +

This is the complete list of members for crow::Router, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + +
blueprints() (defined in crow::Router)crow::Routerinline
catchall_rule() (defined in crow::Router)crow::Routerinline
debug_print() (defined in crow::Router)crow::Routerinline
default_exception_handler(response &res) (defined in crow::Router)crow::Routerinlinestatic
exception_handler() (defined in crow::Router)crow::Routerinline
get_error(unsigned short code, routing_handle_result &found, const request &req, response &res)crow::Routerinline
get_found_bp(std::vector< uint16_t > &bp_i, std::vector< Blueprint * > &blueprints, std::vector< Blueprint * > &found_bps, uint16_t index=0) (defined in crow::Router)crow::Routerinline
get_recursive_child_methods(Blueprint *blueprint, std::vector< HTTPMethod > &methods) (defined in crow::Router)crow::Routerinline
handle(request &req, response &res, routing_handle_result found) (defined in crow::Router)crow::Routerinline
handle_initial(request &req, response &res) (defined in crow::Router)crow::Routerinline
handle_rule(BaseRule *rule, crow::request &req, crow::response &res, const crow::routing_params &rp) (defined in crow::Router)crow::Routerinline
handle_rule(BaseRule *rule, crow::request &req, crow::response &res, const crow::routing_params &rp) (defined in crow::Router)crow::Routerinline
handle_upgrade(const request &req, response &res, Adaptor &&adaptor) (defined in crow::Router)crow::Routerinline
internal_add_rule_object(const std::string &rule, BaseRule *ruleObject) (defined in crow::Router)crow::Routerinline
internal_add_rule_object(const std::string &rule, BaseRule *ruleObject, const uint16_t &BP_index, std::vector< Blueprint * > &blueprints) (defined in crow::Router)crow::Routerinline
new_rule_dynamic(const std::string &rule) (defined in crow::Router)crow::Routerinline
new_rule_tagged(const std::string &rule) (defined in crow::Router)crow::Routerinline
register_blueprint(Blueprint &blueprint) (defined in crow::Router)crow::Routerinline
Router() (defined in crow::Router)crow::Routerinline
validate() (defined in crow::Router)crow::Routerinline
validate_bp() (defined in crow::Router)crow::Routerinline
validate_bp(std::vector< Blueprint * > blueprints, detail::middleware_indices &current_mw) (defined in crow::Router)crow::Routerinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_router.html b/1.2/reference/classcrow_1_1_router.html new file mode 100644 index 000000000..c8b4e0ef1 --- /dev/null +++ b/1.2/reference/classcrow_1_1_router.html @@ -0,0 +1,208 @@ + + + + + + + + Crow: crow::Router Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ + +
+ +

Handles matching requests to existing rules and upgrade requests. + More...

+ +

#include <routing.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

+DynamicRulenew_rule_dynamic (const std::string &rule)
 
+template<uint64_t N>
black_magic::arguments< N >::type::template rebind< TaggedRule > & new_rule_tagged (const std::string &rule)
 
+CatchallRulecatchall_rule ()
 
+void internal_add_rule_object (const std::string &rule, BaseRule *ruleObject)
 
+void internal_add_rule_object (const std::string &rule, BaseRule *ruleObject, const uint16_t &BP_index, std::vector< Blueprint * > &blueprints)
 
+void register_blueprint (Blueprint &blueprint)
 
+void get_recursive_child_methods (Blueprint *blueprint, std::vector< HTTPMethod > &methods)
 
+void validate_bp ()
 
+void validate_bp (std::vector< Blueprint * > blueprints, detail::middleware_indices &current_mw)
 
+void validate ()
 
+template<typename Adaptor >
void handle_upgrade (const request &req, response &res, Adaptor &&adaptor)
 
+void get_found_bp (std::vector< uint16_t > &bp_i, std::vector< Blueprint * > &blueprints, std::vector< Blueprint * > &found_bps, uint16_t index=0)
 
+std::string get_error (unsigned short code, routing_handle_result &found, const request &req, response &res)
 Is used to handle errors, you insert the error code, found route, request, and response. and it'll either call the appropriate catchall route (considering the blueprint system) and send you a status string (which is mainly used for debug messages), or just set the response code to the proper error code.
 
+std::unique_ptr< routing_handle_resulthandle_initial (request &req, response &res)
 
+template<typename App >
void handle (request &req, response &res, routing_handle_result found)
 
+template<typename App >
std::enable_if< std::tuple_size< typename App::mw_container_t >::value !=0, void >::type handle_rule (BaseRule *rule, crow::request &req, crow::response &res, const crow::routing_params &rp)
 
+template<typename App >
std::enable_if< std::tuple_size< typename App::mw_container_t >::value==0, void >::type handle_rule (BaseRule *rule, crow::request &req, crow::response &res, const crow::routing_params &rp)
 
+void debug_print ()
 
+std::vector< Blueprint * > & blueprints ()
 
+std::function< void(crow::response &)> & exception_handler ()
 
+ + + +

+Static Public Member Functions

+static void default_exception_handler (response &res)
 
+

Detailed Description

+

Handles matching requests to existing rules and upgrade requests.

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_router.js b/1.2/reference/classcrow_1_1_router.js new file mode 100644 index 000000000..423db8c01 --- /dev/null +++ b/1.2/reference/classcrow_1_1_router.js @@ -0,0 +1,24 @@ +var classcrow_1_1_router = +[ + [ "Router", "classcrow_1_1_router.html#ae5c4c84e7b66b23c20a893bf320137de", null ], + [ "blueprints", "classcrow_1_1_router.html#afe22b2cfd1ada8c06d9e181d155cda61", null ], + [ "catchall_rule", "classcrow_1_1_router.html#ad757b52858f405c09e7757e1e1b1acb6", null ], + [ "debug_print", "classcrow_1_1_router.html#a61157adad80f901413a4023d8fb0fd9d", null ], + [ "exception_handler", "classcrow_1_1_router.html#a411dcf8f4132070ff486a10d448ab8e7", null ], + [ "get_error", "classcrow_1_1_router.html#a39beca1acc1997c68db0d34556b6cf87", null ], + [ "get_found_bp", "classcrow_1_1_router.html#a4d65ef343dc5bfbc6c80cb0987a19151", null ], + [ "get_recursive_child_methods", "classcrow_1_1_router.html#a6438f06d942775e79cc4c12cb954b658", null ], + [ "handle", "classcrow_1_1_router.html#a20232543268cd08d681a29d6c740fc4f", null ], + [ "handle_initial", "classcrow_1_1_router.html#a45e8c0f1910b045f3c97fe7718447560", null ], + [ "handle_rule", "classcrow_1_1_router.html#aafb79b1b02c1f2739a74240e89bacf92", null ], + [ "handle_rule", "classcrow_1_1_router.html#a1d965ad074d377e6fc87afdcdad20595", null ], + [ "handle_upgrade", "classcrow_1_1_router.html#a2b37f05675d075c3de79f6a4de42320d", null ], + [ "internal_add_rule_object", "classcrow_1_1_router.html#a67549da074b6c19280db15a25747417d", null ], + [ "internal_add_rule_object", "classcrow_1_1_router.html#a20f16874473f813c92ee8b9df771a437", null ], + [ "new_rule_dynamic", "classcrow_1_1_router.html#ac3ccb4f72fa43650356b485d744c49cb", null ], + [ "new_rule_tagged", "classcrow_1_1_router.html#a7e20f1e99321ad71db0eb936d2fb267e", null ], + [ "register_blueprint", "classcrow_1_1_router.html#a303e99f0109524b148d8d0a032367e8e", null ], + [ "validate", "classcrow_1_1_router.html#a7916aa9620d6c6af2389af0d877ea9d9", null ], + [ "validate_bp", "classcrow_1_1_router.html#a8e286f22cb96519b15b962470387e724", null ], + [ "validate_bp", "classcrow_1_1_router.html#aac8617b861a3f936334a1d502425e759", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_server-members.html b/1.2/reference/classcrow_1_1_server-members.html new file mode 100644 index 000000000..8b9534570 --- /dev/null +++ b/1.2/reference/classcrow_1_1_server-members.html @@ -0,0 +1,127 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::Server< Handler, Adaptor, Middlewares > Member List
+
+
+ +

This is the complete list of members for crow::Server< Handler, Adaptor, Middlewares >, including all inherited members.

+ + + + + + + + + +
on_tick() (defined in crow::Server< Handler, Adaptor, Middlewares >)crow::Server< Handler, Adaptor, Middlewares >inline
run() (defined in crow::Server< Handler, Adaptor, Middlewares >)crow::Server< Handler, Adaptor, Middlewares >inline
Server(Handler *handler, std::string bindaddr, uint16_t port, std::string server_name=std::string("Crow/")+VERSION, std::tuple< Middlewares... > *middlewares=nullptr, uint16_t concurrency=1, uint8_t timeout=5, typename Adaptor::context *adaptor_ctx=nullptr) (defined in crow::Server< Handler, Adaptor, Middlewares >)crow::Server< Handler, Adaptor, Middlewares >inline
set_tick_function(std::chrono::milliseconds d, std::function< void()> f) (defined in crow::Server< Handler, Adaptor, Middlewares >)crow::Server< Handler, Adaptor, Middlewares >inline
signal_add(int signal_number) (defined in crow::Server< Handler, Adaptor, Middlewares >)crow::Server< Handler, Adaptor, Middlewares >inline
signal_clear() (defined in crow::Server< Handler, Adaptor, Middlewares >)crow::Server< Handler, Adaptor, Middlewares >inline
stop() (defined in crow::Server< Handler, Adaptor, Middlewares >)crow::Server< Handler, Adaptor, Middlewares >inline
wait_for_start()crow::Server< Handler, Adaptor, Middlewares >inline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_server.html b/1.2/reference/classcrow_1_1_server.html new file mode 100644 index 000000000..5b1c3c9b2 --- /dev/null +++ b/1.2/reference/classcrow_1_1_server.html @@ -0,0 +1,152 @@ + + + + + + + + Crow: crow::Server< Handler, Adaptor, Middlewares > Class Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::Server< Handler, Adaptor, Middlewares > Class Template Reference
+
+
+ + + + + + + + + + + + + + + + + + + +

+Public Member Functions

Server (Handler *handler, std::string bindaddr, uint16_t port, std::string server_name=std::string("Crow/")+VERSION, std::tuple< Middlewares... > *middlewares=nullptr, uint16_t concurrency=1, uint8_t timeout=5, typename Adaptor::context *adaptor_ctx=nullptr)
 
+void set_tick_function (std::chrono::milliseconds d, std::function< void()> f)
 
+void on_tick ()
 
+void run ()
 
+void stop ()
 
+void wait_for_start ()
 Wait until the server has properly started.
 
+void signal_clear ()
 
+void signal_add (int signal_number)
 
+
The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_server.js b/1.2/reference/classcrow_1_1_server.js new file mode 100644 index 000000000..7b07ac257 --- /dev/null +++ b/1.2/reference/classcrow_1_1_server.js @@ -0,0 +1,11 @@ +var classcrow_1_1_server = +[ + [ "Server", "classcrow_1_1_server.html#af7960abfbe9b7b4f53a0f8b774b5015a", null ], + [ "on_tick", "classcrow_1_1_server.html#a932e5790236d8f2dc4c973e357c6bd43", null ], + [ "run", "classcrow_1_1_server.html#a90b072e9143f9417ce9dd30510a07495", null ], + [ "set_tick_function", "classcrow_1_1_server.html#abcd3d2395e5ca2a44fd58eacfbb1ed65", null ], + [ "signal_add", "classcrow_1_1_server.html#adf23b269d0dfe6e39d1d2d8ee92ca653", null ], + [ "signal_clear", "classcrow_1_1_server.html#ae4683f3386b9f3f10013f42d01cdd769", null ], + [ "stop", "classcrow_1_1_server.html#aff2067a94286dd5a584a187cbce369f5", null ], + [ "wait_for_start", "classcrow_1_1_server.html#a0b63b4a3da3acbb2a1870db19279f580", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_tagged_rule-members.html b/1.2/reference/classcrow_1_1_tagged_rule-members.html new file mode 100644 index 000000000..6985dea06 --- /dev/null +++ b/1.2/reference/classcrow_1_1_tagged_rule-members.html @@ -0,0 +1,147 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::TaggedRule< Args > Member List
+
+
+ +

This is the complete list of members for crow::TaggedRule< Args >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
added_ (defined in crow::BaseRule)crow::BaseRuleprotected
BaseRule(std::string rule) (defined in crow::BaseRule)crow::BaseRuleinline
custom_templates_base (defined in crow::BaseRule)crow::BaseRule
foreach_method(F f) (defined in crow::BaseRule)crow::BaseRuleinline
get_methods() (defined in crow::BaseRule)crow::BaseRuleinline
handle(request &req, response &res, const routing_params &params) override (defined in crow::TaggedRule< Args >)crow::TaggedRule< Args >inlinevirtual
handle_upgrade(const request &, response &res, SocketAdaptor &&) (defined in crow::BaseRule)crow::BaseRuleinlinevirtual
handle_upgrade(const request &, response &res, SSLAdaptor &&) (defined in crow::BaseRule)crow::BaseRuleinlinevirtual
is_added() (defined in crow::BaseRule)crow::BaseRuleinline
methods(HTTPMethod method) (defined in crow::RuleParameterTraits< TaggedRule< Args... > >)crow::RuleParameterTraits< TaggedRule< Args... > >inline
methods(HTTPMethod method, MethodArgs... args_method) (defined in crow::RuleParameterTraits< TaggedRule< Args... > >)crow::RuleParameterTraits< TaggedRule< Args... > >inline
methods_ (defined in crow::BaseRule)crow::BaseRuleprotected
middlewares()crow::RuleParameterTraits< TaggedRule< Args... > >inline
mw_indices_ (defined in crow::BaseRule)crow::BaseRuleprotected
name(std::string name) noexcept (defined in crow::RuleParameterTraits< TaggedRule< Args... > >)crow::RuleParameterTraits< TaggedRule< Args... > >inline
name_ (defined in crow::BaseRule)crow::BaseRuleprotected
operator()(Func &&f) (defined in crow::TaggedRule< Args >)crow::TaggedRule< Args >inline
operator()(std::string name, Func &&f) (defined in crow::TaggedRule< Args >)crow::TaggedRule< Args >inline
rule() (defined in crow::BaseRule)crow::BaseRuleinline
rule_ (defined in crow::BaseRule)crow::BaseRuleprotected
rule_to_upgrade_ (defined in crow::BaseRule)crow::BaseRuleprotected
self_t typedef (defined in crow::TaggedRule< Args >)crow::TaggedRule< Args >
set_added() (defined in crow::BaseRule)crow::BaseRuleinline
TaggedRule(std::string rule) (defined in crow::TaggedRule< Args >)crow::TaggedRule< Args >inline
upgrade() (defined in crow::BaseRule)crow::BaseRuleinline
validate() override (defined in crow::TaggedRule< Args >)crow::TaggedRule< Args >inlinevirtual
websocket(App *app) (defined in crow::RuleParameterTraits< TaggedRule< Args... > >)crow::RuleParameterTraits< TaggedRule< Args... > >inline
~BaseRule() (defined in crow::BaseRule)crow::BaseRuleinlinevirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_tagged_rule.html b/1.2/reference/classcrow_1_1_tagged_rule.html new file mode 100644 index 000000000..08f63ed12 --- /dev/null +++ b/1.2/reference/classcrow_1_1_tagged_rule.html @@ -0,0 +1,247 @@ + + + + + + + + Crow: crow::TaggedRule< Args > Class Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::TaggedRule< Args > Class Template Reference
+
+
+ +

Default rule created when CROW_ROUTE is called. + More...

+ +

#include <routing.h>

+
+Inheritance diagram for crow::TaggedRule< Args >:
+
+
+ + +crow::BaseRule +crow::RuleParameterTraits< TaggedRule< Args... > > + +
+ + + + + + + +

+Public Types

+using self_t = TaggedRule< Args... >
 
- Public Types inherited from crow::RuleParameterTraits< TaggedRule< Args... > >
+using self_t = TaggedRule< Args... >
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

TaggedRule (std::string rule)
 
+void validate () override
 
+template<typename Func >
void operator() (Func &&f)
 
+template<typename Func >
void operator() (std::string name, Func &&f)
 
+void handle (request &req, response &res, const routing_params &params) override
 
- Public Member Functions inherited from crow::BaseRule
BaseRule (std::string rule)
 
+void set_added ()
 
+bool is_added ()
 
+std::unique_ptr< BaseRuleupgrade ()
 
+virtual void handle_upgrade (const request &, response &res, SocketAdaptor &&)
 
+virtual void handle_upgrade (const request &, response &res, SSLAdaptor &&)
 
+uint32_t get_methods ()
 
+template<typename F >
void foreach_method (F f)
 
+const std::string & rule ()
 
- Public Member Functions inherited from crow::RuleParameterTraits< TaggedRule< Args... > >
+WebSocketRule< App > & websocket (App *app)
 
+self_tname (std::string name) noexcept
 
+self_tmethods (HTTPMethod method)
 
+self_tmethods (HTTPMethod method, MethodArgs... args_method)
 
+self_tmiddlewares ()
 Enable local middleware for this handler.
 
+ + + + + + + + + + + + + + + + + +

+Additional Inherited Members

- Public Attributes inherited from crow::BaseRule
+std::string custom_templates_base
 
- Protected Attributes inherited from crow::BaseRule
+uint32_t methods_ {1 << static_cast<int>(HTTPMethod::Get)}
 
+std::string rule_
 
+std::string name_
 
+bool added_ {false}
 
+std::unique_ptr< BaseRulerule_to_upgrade_
 
+detail::middleware_indices mw_indices_
 
+

Detailed Description

+

template<typename... Args>
+class crow::TaggedRule< Args >

+ +

Default rule created when CROW_ROUTE is called.

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_tagged_rule.js b/1.2/reference/classcrow_1_1_tagged_rule.js new file mode 100644 index 000000000..b4f5ca701 --- /dev/null +++ b/1.2/reference/classcrow_1_1_tagged_rule.js @@ -0,0 +1,9 @@ +var classcrow_1_1_tagged_rule = +[ + [ "self_t", "classcrow_1_1_tagged_rule.html#aae5d1683e30a8d4e058666b7d12dea14", null ], + [ "TaggedRule", "classcrow_1_1_tagged_rule.html#a058a079101cee2bcc5936c785c6c76f6", null ], + [ "handle", "classcrow_1_1_tagged_rule.html#adcbf056e4db8f2673bc7c9bcb1608588", null ], + [ "operator()", "classcrow_1_1_tagged_rule.html#aa4edba914ac43596699df3b8bdf2b7b8", null ], + [ "operator()", "classcrow_1_1_tagged_rule.html#aeed24311bbc5faa60e5c07ffcad2a5de", null ], + [ "validate", "classcrow_1_1_tagged_rule.html#aafb046bbb0f1b47c1d56bfae72ef390a", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_tagged_rule.png b/1.2/reference/classcrow_1_1_tagged_rule.png new file mode 100644 index 000000000..0c5ad702a Binary files /dev/null and b/1.2/reference/classcrow_1_1_tagged_rule.png differ diff --git a/1.2/reference/classcrow_1_1_trie-members.html b/1.2/reference/classcrow_1_1_trie-members.html new file mode 100644 index 000000000..441bef794 --- /dev/null +++ b/1.2/reference/classcrow_1_1_trie-members.html @@ -0,0 +1,127 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::Trie Member List
+
+
+ +

This is the complete list of members for crow::Trie, including all inherited members.

+ + + + + + + + + +
add(const std::string &url, uint16_t rule_index, unsigned bp_prefix_length=0, uint16_t blueprint_index=INVALID_BP_ID) (defined in crow::Trie)crow::Trieinline
debug_print() (defined in crow::Trie)crow::Trieinline
find(const std::string &req_url, const Node &node, unsigned pos=0, routing_params *params=nullptr, std::vector< uint16_t > *blueprints=nullptr) const (defined in crow::Trie)crow::Trieinline
find(const std::string &req_url) const (defined in crow::Trie)crow::Trieinline
is_empty()crow::Trieinline
optimize() (defined in crow::Trie)crow::Trieinline
Trie() (defined in crow::Trie)crow::Trieinline
validate() (defined in crow::Trie)crow::Trieinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_trie.html b/1.2/reference/classcrow_1_1_trie.html new file mode 100644 index 000000000..919493c36 --- /dev/null +++ b/1.2/reference/classcrow_1_1_trie.html @@ -0,0 +1,162 @@ + + + + + + + + Crow: crow::Trie Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::Trie Class Reference
+
+
+ +

A search tree. + More...

+ +

#include <routing.h>

+ + + + +

+Classes

struct  Node
 
+ + + + + + + + + + + + + + + + +

+Public Member Functions

+bool is_empty ()
 Check whether or not the trie is empty.
 
+void optimize ()
 
+void debug_print ()
 
+void validate ()
 
+routing_handle_result find (const std::string &req_url, const Node &node, unsigned pos=0, routing_params *params=nullptr, std::vector< uint16_t > *blueprints=nullptr) const
 
+routing_handle_result find (const std::string &req_url) const
 
+void add (const std::string &url, uint16_t rule_index, unsigned bp_prefix_length=0, uint16_t blueprint_index=INVALID_BP_ID)
 
+

Detailed Description

+

A search tree.

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_trie.js b/1.2/reference/classcrow_1_1_trie.js new file mode 100644 index 000000000..b4e475158 --- /dev/null +++ b/1.2/reference/classcrow_1_1_trie.js @@ -0,0 +1,12 @@ +var classcrow_1_1_trie = +[ + [ "Node", "structcrow_1_1_trie_1_1_node.html", "structcrow_1_1_trie_1_1_node" ], + [ "Trie", "classcrow_1_1_trie.html#ae6b070e1e25b6c5d77cfb2aa05473d73", null ], + [ "add", "classcrow_1_1_trie.html#a3a71f4488027eace41a219f79d862620", null ], + [ "debug_print", "classcrow_1_1_trie.html#a9ac17b6ae0f96dc94b595bb704a89101", null ], + [ "find", "classcrow_1_1_trie.html#ae7a7ee733beb27778c248d1845810ed0", null ], + [ "find", "classcrow_1_1_trie.html#abc0bd160cacaf955c4940e8f30632c42", null ], + [ "is_empty", "classcrow_1_1_trie.html#af2cada415bae6140779323f453a5a146", null ], + [ "optimize", "classcrow_1_1_trie.html#a176514f9aa126ad93008022e278e88a8", null ], + [ "validate", "classcrow_1_1_trie.html#a77dcd4729633ce992fc210eeb327dfb5", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_web_socket_rule-members.html b/1.2/reference/classcrow_1_1_web_socket_rule-members.html new file mode 100644 index 000000000..8a4024667 --- /dev/null +++ b/1.2/reference/classcrow_1_1_web_socket_rule-members.html @@ -0,0 +1,153 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::WebSocketRule< App > Member List
+
+
+ +

This is the complete list of members for crow::WebSocketRule< App >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
accept_handler_ (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >protected
added_ (defined in crow::BaseRule)crow::BaseRuleprotected
app_ (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >protected
BaseRule(std::string rule) (defined in crow::BaseRule)crow::BaseRuleinline
close_handler_ (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >protected
custom_templates_base (defined in crow::BaseRule)crow::BaseRule
error_handler_ (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >protected
foreach_method(F f) (defined in crow::BaseRule)crow::BaseRuleinline
get_methods() (defined in crow::BaseRule)crow::BaseRuleinline
handle(request &, response &res, const routing_params &) override (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >inlinevirtual
handle_upgrade(const request &req, response &, SocketAdaptor &&adaptor) override (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >inlinevirtual
handle_upgrade(const request &req, response &, SSLAdaptor &&adaptor) override (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >inlinevirtual
is_added() (defined in crow::BaseRule)crow::BaseRuleinline
max_payload(uint64_t max_payload)crow::WebSocketRule< App >inline
max_payload_ (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >protected
max_payload_override_ (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >protected
message_handler_ (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >protected
methods_ (defined in crow::BaseRule)crow::BaseRuleprotected
mw_indices_ (defined in crow::BaseRule)crow::BaseRuleprotected
name_ (defined in crow::BaseRule)crow::BaseRuleprotected
onaccept(Func f) (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >inline
onclose(Func f) (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >inline
onerror(Func f) (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >inline
onmessage(Func f) (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >inline
onopen(Func f) (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >inline
open_handler_ (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >protected
rule() (defined in crow::BaseRule)crow::BaseRuleinline
rule_ (defined in crow::BaseRule)crow::BaseRuleprotected
rule_to_upgrade_ (defined in crow::BaseRule)crow::BaseRuleprotected
set_added() (defined in crow::BaseRule)crow::BaseRuleinline
upgrade() (defined in crow::BaseRule)crow::BaseRuleinline
validate() override (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >inlinevirtual
WebSocketRule(std::string rule, App *app) (defined in crow::WebSocketRule< App >)crow::WebSocketRule< App >inline
~BaseRule() (defined in crow::BaseRule)crow::BaseRuleinlinevirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_web_socket_rule.html b/1.2/reference/classcrow_1_1_web_socket_rule.html new file mode 100644 index 000000000..a19f6a92d --- /dev/null +++ b/1.2/reference/classcrow_1_1_web_socket_rule.html @@ -0,0 +1,263 @@ + + + + + + + + Crow: crow::WebSocketRule< App > Class Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::WebSocketRule< App > Class Template Reference
+
+
+ +

A rule dealing with websockets. + More...

+ +

#include <routing.h>

+
+Inheritance diagram for crow::WebSocketRule< App >:
+
+
+ + +crow::BaseRule + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

WebSocketRule (std::string rule, App *app)
 
+void validate () override
 
+void handle (request &, response &res, const routing_params &) override
 
+void handle_upgrade (const request &req, response &, SocketAdaptor &&adaptor) override
 
+void handle_upgrade (const request &req, response &, SSLAdaptor &&adaptor) override
 
+self_tmax_payload (uint64_t max_payload)
 Override the global payload limit for this single WebSocket rule.
 
+template<typename Func >
self_tonopen (Func f)
 
+template<typename Func >
self_tonmessage (Func f)
 
+template<typename Func >
self_tonclose (Func f)
 
+template<typename Func >
self_tonerror (Func f)
 
+template<typename Func >
self_tonaccept (Func f)
 
- Public Member Functions inherited from crow::BaseRule
BaseRule (std::string rule)
 
+void set_added ()
 
+bool is_added ()
 
+std::unique_ptr< BaseRuleupgrade ()
 
+uint32_t get_methods ()
 
+template<typename F >
void foreach_method (F f)
 
+const std::string & rule ()
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Protected Attributes

+Appapp_
 
+std::function< void(crow::websocket::connection &)> open_handler_
 
+std::function< void(crow::websocket::connection &, const std::string &, bool)> message_handler_
 
+std::function< void(crow::websocket::connection &, const std::string &)> close_handler_
 
+std::function< void(crow::websocket::connection &, const std::string &)> error_handler_
 
+std::function< bool(const crow::request &, void **)> accept_handler_
 
+uint64_t max_payload_
 
+bool max_payload_override_ = false
 
- Protected Attributes inherited from crow::BaseRule
+uint32_t methods_ {1 << static_cast<int>(HTTPMethod::Get)}
 
+std::string rule_
 
+std::string name_
 
+bool added_ {false}
 
+std::unique_ptr< BaseRulerule_to_upgrade_
 
+detail::middleware_indices mw_indices_
 
+ + + + +

+Additional Inherited Members

- Public Attributes inherited from crow::BaseRule
+std::string custom_templates_base
 
+

Detailed Description

+

template<typename App>
+class crow::WebSocketRule< App >

+ +

A rule dealing with websockets.

+

Provides the interface for the user to put in the necessary handlers for a websocket to work.

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_web_socket_rule.js b/1.2/reference/classcrow_1_1_web_socket_rule.js new file mode 100644 index 000000000..9d3a3f164 --- /dev/null +++ b/1.2/reference/classcrow_1_1_web_socket_rule.js @@ -0,0 +1,22 @@ +var classcrow_1_1_web_socket_rule = +[ + [ "WebSocketRule", "classcrow_1_1_web_socket_rule.html#a17c9e24812ae1d436ab9be61768966c8", null ], + [ "handle", "classcrow_1_1_web_socket_rule.html#a921adb281f701d53187d9f20294010da", null ], + [ "handle_upgrade", "classcrow_1_1_web_socket_rule.html#af01bd035e8753d8e4fc7728b2d5d69e8", null ], + [ "handle_upgrade", "classcrow_1_1_web_socket_rule.html#aba2c2bc84f24c46b15cff19a2990ea9b", null ], + [ "max_payload", "classcrow_1_1_web_socket_rule.html#ad4d8b25025e767fbe9af7f7c4263c2cb", null ], + [ "onaccept", "classcrow_1_1_web_socket_rule.html#a062d0ed4e4cc9be6335be0fd1ac2966c", null ], + [ "onclose", "classcrow_1_1_web_socket_rule.html#a8aec1859be775d6e82eab9e300a895c4", null ], + [ "onerror", "classcrow_1_1_web_socket_rule.html#a45aa6ed4f0aa5f1af9e8b87ed8020e76", null ], + [ "onmessage", "classcrow_1_1_web_socket_rule.html#acbc2415278899fddbba3de7888de2a6a", null ], + [ "onopen", "classcrow_1_1_web_socket_rule.html#ab6e22fe1928da26bbc469cf1ea8c6d9d", null ], + [ "validate", "classcrow_1_1_web_socket_rule.html#abe8e71a9a3845698f432307f282be0cc", null ], + [ "accept_handler_", "classcrow_1_1_web_socket_rule.html#a08de36976f908322a8ee86edb4a8ba23", null ], + [ "app_", "classcrow_1_1_web_socket_rule.html#aab0e3390b3306fdc048f9fadaed50195", null ], + [ "close_handler_", "classcrow_1_1_web_socket_rule.html#a68d2f5f5d6a6185bbb1b0faf8d8bbb12", null ], + [ "error_handler_", "classcrow_1_1_web_socket_rule.html#ae8d7bf00757eb5727fc5d0eb479cc9df", null ], + [ "max_payload_", "classcrow_1_1_web_socket_rule.html#a9ee993bdbed14eccd5232ba8cc472d52", null ], + [ "max_payload_override_", "classcrow_1_1_web_socket_rule.html#a4f169c0aedfa2161fb2cdd8e456fb5c0", null ], + [ "message_handler_", "classcrow_1_1_web_socket_rule.html#a9ecbb3cbccb90163fabcea7867b8f9f9", null ], + [ "open_handler_", "classcrow_1_1_web_socket_rule.html#ac05e9a53b234528328e4d00c870e57b5", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1_web_socket_rule.png b/1.2/reference/classcrow_1_1_web_socket_rule.png new file mode 100644 index 000000000..ee48b1600 Binary files /dev/null and b/1.2/reference/classcrow_1_1_web_socket_rule.png differ diff --git a/1.2/reference/classcrow_1_1detail_1_1task__timer-members.html b/1.2/reference/classcrow_1_1detail_1_1task__timer-members.html new file mode 100644 index 000000000..3298b0b4f --- /dev/null +++ b/1.2/reference/classcrow_1_1detail_1_1task__timer-members.html @@ -0,0 +1,128 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::task_timer Member List
+
+
+ +

This is the complete list of members for crow::detail::task_timer, including all inherited members.

+ + + + + + + + + + +
cancel(identifier_type id) (defined in crow::detail::task_timer)crow::detail::task_timerinline
get_default_timeout() constcrow::detail::task_timerinline
identifier_type typedef (defined in crow::detail::task_timer)crow::detail::task_timer
schedule(const task_type &task)crow::detail::task_timerinline
schedule(const task_type &task, std::uint8_t timeout)crow::detail::task_timerinline
set_default_timeout(std::uint8_t timeout)crow::detail::task_timerinline
task_timer(asio::io_service &io_service) (defined in crow::detail::task_timer)crow::detail::task_timerinline
task_type typedef (defined in crow::detail::task_timer)crow::detail::task_timer
~task_timer() (defined in crow::detail::task_timer)crow::detail::task_timerinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1detail_1_1task__timer.html b/1.2/reference/classcrow_1_1detail_1_1task__timer.html new file mode 100644 index 000000000..fa9d336a2 --- /dev/null +++ b/1.2/reference/classcrow_1_1detail_1_1task__timer.html @@ -0,0 +1,272 @@ + + + + + + + + Crow: crow::detail::task_timer Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::task_timer Class Reference
+
+
+ +

A class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 second. + More...

+ +

#include <task_timer.h>

+ + + + + + +

+Public Types

+using task_type = std::function< void()>
 
+using identifier_type = size_t
 
+ + + + + + + + + + + + + + + + + +

+Public Member Functions

task_timer (asio::io_service &io_service)
 
+void cancel (identifier_type id)
 
identifier_type schedule (const task_type &task)
 Schedule the given task to be executed after the default amount of ticks. More...
 
identifier_type schedule (const task_type &task, std::uint8_t timeout)
 Schedule the given task to be executed after the given time. More...
 
void set_default_timeout (std::uint8_t timeout)
 Set the default timeout for this task_timer instance. (Default: 5) More...
 
+std::uint8_t get_default_timeout () const
 Get the default timeout. (Default: 5)
 
+

Detailed Description

+

A class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 second.

+

Member Function Documentation

+ +

◆ schedule() [1/2]

+ +
+
+ + + + + +
+ + + + + + + + +
identifier_type crow::detail::task_timer::schedule (const task_type & task)
+
+inline
+
+ +

Schedule the given task to be executed after the default amount of ticks.

+
Returns
identifier_type Used to cancel the thread. It is not bound to this task_timer instance and in some cases could lead to undefined behavior if used with other task_timer objects or after the task has been successfully executed.
+ +
+
+ +

◆ schedule() [2/2]

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
identifier_type crow::detail::task_timer::schedule (const task_type & task,
std::uint8_t timeout 
)
+
+inline
+
+ +

Schedule the given task to be executed after the given time.

+
Parameters
+ + +
timeoutThe amount of ticks (seconds) to wait before execution.
+
+
+
Returns
identifier_type Used to cancel the thread. It is not bound to this task_timer instance and in some cases could lead to undefined behavior if used with other task_timer objects or after the task has been successfully executed.
+ +
+
+ +

◆ set_default_timeout()

+ +
+
+ + + + + +
+ + + + + + + + +
void crow::detail::task_timer::set_default_timeout (std::uint8_t timeout)
+
+inline
+
+ +

Set the default timeout for this task_timer instance. (Default: 5)

+
Parameters
+ + +
timeoutThe amount of ticks (seconds) to wait before execution.
+
+
+ +
+
+
The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1detail_1_1task__timer.js b/1.2/reference/classcrow_1_1detail_1_1task__timer.js new file mode 100644 index 000000000..b2a21c69a --- /dev/null +++ b/1.2/reference/classcrow_1_1detail_1_1task__timer.js @@ -0,0 +1,12 @@ +var classcrow_1_1detail_1_1task__timer = +[ + [ "identifier_type", "classcrow_1_1detail_1_1task__timer.html#aab902a1634760b439ab748d1cb0af56a", null ], + [ "task_type", "classcrow_1_1detail_1_1task__timer.html#a3d26d472f56d5085b08e3045585618f1", null ], + [ "task_timer", "classcrow_1_1detail_1_1task__timer.html#a25715a0b6a6fae2d87c3aaef1d9387be", null ], + [ "~task_timer", "classcrow_1_1detail_1_1task__timer.html#aea48cde928f27e3ff011ecd6c8387e99", null ], + [ "cancel", "classcrow_1_1detail_1_1task__timer.html#a05b9d2725c0992aace3c50c942d56e92", null ], + [ "get_default_timeout", "classcrow_1_1detail_1_1task__timer.html#ae11e1259251e562ea3be457457b3b287", null ], + [ "schedule", "classcrow_1_1detail_1_1task__timer.html#ac1a35eb9b85887368b65e01c07d3c91c", null ], + [ "schedule", "classcrow_1_1detail_1_1task__timer.html#a777c073f4e895c638d2cbbf6a27ad1fa", null ], + [ "set_default_timeout", "classcrow_1_1detail_1_1task__timer.html#aa67cab7afc1646a4127b0c6c97e5f5ea", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1json_1_1rvalue-members.html b/1.2/reference/classcrow_1_1json_1_1rvalue-members.html new file mode 100644 index 000000000..94bc07ae1 --- /dev/null +++ b/1.2/reference/classcrow_1_1json_1_1rvalue-members.html @@ -0,0 +1,157 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::json::rvalue Member List
+
+
+ +

This is the complete list of members for crow::json::rvalue, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
b() constcrow::json::rvalueinline
begin() const (defined in crow::json::rvalue)crow::json::rvalueinline
count(const std::string &str) (defined in crow::json::rvalue)crow::json::rvalueinline
d() constcrow::json::rvalueinline
end() const (defined in crow::json::rvalue)crow::json::rvalueinline
error() const (defined in crow::json::rvalue)crow::json::rvalueinline
has(const char *str) constcrow::json::rvalueinline
has(const std::string &str) const (defined in crow::json::rvalue)crow::json::rvalueinline
i() constcrow::json::rvalueinline
key() const (defined in crow::json::rvalue)crow::json::rvalueinline
keys() const (defined in crow::json::rvalue)crow::json::rvalueinline
lo()crow::json::rvalueinline
load (defined in crow::json::rvalue)crow::json::rvaluefriend
load_nocopy_internal (defined in crow::json::rvalue)crow::json::rvaluefriend
nt() constcrow::json::rvalueinline
operator bool() const noexcept (defined in crow::json::rvalue)crow::json::rvalueinlineexplicit
operator int() const (defined in crow::json::rvalue)crow::json::rvalueinlineexplicit
operator int64_t() const (defined in crow::json::rvalue)crow::json::rvalueinlineexplicit
operator std::string() constcrow::json::rvalueinlineexplicit
operator uint64_t() const (defined in crow::json::rvalue)crow::json::rvalueinlineexplicit
operator<< (defined in crow::json::rvalue)crow::json::rvaluefriend
operator=(const rvalue &r) (defined in crow::json::rvalue)crow::json::rvalueinline
operator=(rvalue &&r) noexcept (defined in crow::json::rvalue)crow::json::rvalueinline
operator[](int index) const (defined in crow::json::rvalue)crow::json::rvalueinline
operator[](size_t index) const (defined in crow::json::rvalue)crow::json::rvalueinline
operator[](const char *str) const (defined in crow::json::rvalue)crow::json::rvalueinline
operator[](const std::string &str) const (defined in crow::json::rvalue)crow::json::rvalueinline
rvalue() noexcept (defined in crow::json::rvalue)crow::json::rvalueinline
rvalue(type t) noexcept (defined in crow::json::rvalue)crow::json::rvalueinline
rvalue(type t, char *s, char *e) noexcept (defined in crow::json::rvalue)crow::json::rvalueinline
rvalue(const rvalue &r) (defined in crow::json::rvalue)crow::json::rvalueinline
rvalue(rvalue &&r) noexcept (defined in crow::json::rvalue)crow::json::rvalueinline
s() constcrow::json::rvalueinline
set_error() (defined in crow::json::rvalue)crow::json::rvalueinline
size() const (defined in crow::json::rvalue)crow::json::rvalueinline
t() constcrow::json::rvalueinline
u() constcrow::json::rvalueinline
unescape() constcrow::json::rvalueinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1json_1_1rvalue.html b/1.2/reference/classcrow_1_1json_1_1rvalue.html new file mode 100644 index 000000000..2d471a16e --- /dev/null +++ b/1.2/reference/classcrow_1_1json_1_1rvalue.html @@ -0,0 +1,262 @@ + + + + + + + + Crow: crow::json::rvalue Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::json::rvalue Class Reference
+
+
+ +

JSON read value. + More...

+ +

#include <json.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

rvalue (type t) noexcept
 
rvalue (type t, char *s, char *e) noexcept
 
rvalue (const rvalue &r)
 
rvalue (rvalue &&r) noexcept
 
+rvalueoperator= (const rvalue &r)
 
+rvalueoperator= (rvalue &&r) noexcept
 
operator bool () const noexcept
 
operator int64_t () const
 
operator uint64_t () const
 
operator int () const
 
operator std::string () const
 Return any json value (not object or list) as a string.
 
+type t () const
 The type of the JSON value.
 
+num_type nt () const
 The number type of the JSON value.
 
+int64_t i () const
 The integer value.
 
+uint64_t u () const
 The unsigned integer value.
 
+double d () const
 The double precision floating-point number value.
 
+bool b () const
 The boolean value.
 
+detail::r_string s () const
 The string value.
 
+std::vector< rvaluelo ()
 The list or object value.
 
+void unescape () const
 Convert escaped string character to their original form ("\\n" -> '
+').
 
+bool has (const char *str) const
 Check if the json object has the passed string as a key.
 
+bool has (const std::string &str) const
 
+int count (const std::string &str)
 
+rvaluebegin () const
 
+rvalueend () const
 
+const detail::r_stringkey () const
 
+size_t size () const
 
+const rvalueoperator[] (int index) const
 
+const rvalueoperator[] (size_t index) const
 
+const rvalueoperator[] (const char *str) const
 
+const rvalueoperator[] (const std::string &str) const
 
+void set_error ()
 
+bool error () const
 
+std::vector< std::string > keys () const
 
+ + + + + + + +

+Friends

+rvalue load_nocopy_internal (char *data, size_t size)
 
+rvalue load (const char *data, size_t size)
 
+std::ostream & operator<< (std::ostream &os, const rvalue &r)
 
+

Detailed Description

+

JSON read value.

+

Value can mean any json value, including a JSON object. Read means this class is used to primarily read strings into a JSON value.

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1json_1_1rvalue.js b/1.2/reference/classcrow_1_1json_1_1rvalue.js new file mode 100644 index 000000000..b48be3c86 --- /dev/null +++ b/1.2/reference/classcrow_1_1json_1_1rvalue.js @@ -0,0 +1,41 @@ +var classcrow_1_1json_1_1rvalue = +[ + [ "rvalue", "classcrow_1_1json_1_1rvalue.html#aa2db11774ac831fe243a0e3511946a40", null ], + [ "rvalue", "classcrow_1_1json_1_1rvalue.html#a8b4e22b077d735b29aafc1c1a7e01366", null ], + [ "rvalue", "classcrow_1_1json_1_1rvalue.html#a9eb58f152c08db64e400ebf90df2889e", null ], + [ "rvalue", "classcrow_1_1json_1_1rvalue.html#a834f64380b3479a4497b2ca212559320", null ], + [ "rvalue", "classcrow_1_1json_1_1rvalue.html#ab37b37402eb83aed531868b6a1763f66", null ], + [ "b", "classcrow_1_1json_1_1rvalue.html#a61a5f98c6b0257d53c60a70eeff15490", null ], + [ "begin", "classcrow_1_1json_1_1rvalue.html#ae8305a3db489b6bda4e25072c46a3297", null ], + [ "count", "classcrow_1_1json_1_1rvalue.html#a36b626fa33f7471c184b9b63a01ec9b6", null ], + [ "d", "classcrow_1_1json_1_1rvalue.html#a4a3e33d65b812ed583814a7ac2e1f448", null ], + [ "end", "classcrow_1_1json_1_1rvalue.html#a562de6469b3b68185cc0c1d6972a0909", null ], + [ "error", "classcrow_1_1json_1_1rvalue.html#a4435f7aff4220d5b141b04e559cb964b", null ], + [ "has", "classcrow_1_1json_1_1rvalue.html#a48ac4fff801f365fb2b82f1ed7ebe983", null ], + [ "has", "classcrow_1_1json_1_1rvalue.html#a51444194e66113cb6b04ee123617e003", null ], + [ "i", "classcrow_1_1json_1_1rvalue.html#a1a9a1a3616d6484bf3dcdb941cf8e6da", null ], + [ "key", "classcrow_1_1json_1_1rvalue.html#abdceb190111adaf1b18ddba808414238", null ], + [ "keys", "classcrow_1_1json_1_1rvalue.html#a9421d952be27b80c6d05fd368a714218", null ], + [ "lo", "classcrow_1_1json_1_1rvalue.html#a2b938dacf1809bb38add4ac8bbeb46ed", null ], + [ "nt", "classcrow_1_1json_1_1rvalue.html#a9bf75ffd4603990be7d0eaa192ac54fb", null ], + [ "operator bool", "classcrow_1_1json_1_1rvalue.html#ad8fc5549160087130e44b383a46b4d7c", null ], + [ "operator int", "classcrow_1_1json_1_1rvalue.html#a372e061836bfa0a0bd1b0f1b74d5fc10", null ], + [ "operator int64_t", "classcrow_1_1json_1_1rvalue.html#a6e8890433364ac6dfe7a813cc45a2de3", null ], + [ "operator std::string", "classcrow_1_1json_1_1rvalue.html#a2d5dd8607112a132fe070dee432987ae", null ], + [ "operator uint64_t", "classcrow_1_1json_1_1rvalue.html#ad9e974c1ce818950538053ea2711dced", null ], + [ "operator=", "classcrow_1_1json_1_1rvalue.html#a55b4af62617cf9103cc301892fd6540b", null ], + [ "operator=", "classcrow_1_1json_1_1rvalue.html#a8a6a649a29ef3f3940cb981fb1248076", null ], + [ "operator[]", "classcrow_1_1json_1_1rvalue.html#addce72ce92a3553e8c600ad24c23121c", null ], + [ "operator[]", "classcrow_1_1json_1_1rvalue.html#a8e915f11a880c07f95cd2288a041b4dc", null ], + [ "operator[]", "classcrow_1_1json_1_1rvalue.html#ae9487431a89cf344c9b4188c81604fb6", null ], + [ "operator[]", "classcrow_1_1json_1_1rvalue.html#a58be248be120f4a32416f3c979c70b31", null ], + [ "s", "classcrow_1_1json_1_1rvalue.html#ad94f27a14e60af841219279f70290858", null ], + [ "set_error", "classcrow_1_1json_1_1rvalue.html#a83856d0ddcd6e7236c49b26158ff56a0", null ], + [ "size", "classcrow_1_1json_1_1rvalue.html#a4bf2170d90d5eecf3f4c8811b6ee5e0c", null ], + [ "t", "classcrow_1_1json_1_1rvalue.html#a9c9f7242e4164f4ed690e50e3cf5f4b1", null ], + [ "u", "classcrow_1_1json_1_1rvalue.html#a775273fbbe868c7c8d3a71acdb9ee276", null ], + [ "unescape", "classcrow_1_1json_1_1rvalue.html#a8c60e32c3e25b71c794cc79a4dea466c", null ], + [ "load", "classcrow_1_1json_1_1rvalue.html#a10b60dd760c49dbb7c904e850b298eb5", null ], + [ "load_nocopy_internal", "classcrow_1_1json_1_1rvalue.html#ae5a3f52c3dd924c56c934a35d584077b", null ], + [ "operator<<", "classcrow_1_1json_1_1rvalue.html#a59b7d051c0f407eec8c8bba224d205ff", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1json_1_1wvalue-members.html b/1.2/reference/classcrow_1_1json_1_1wvalue-members.html new file mode 100644 index 000000000..3252c275c --- /dev/null +++ b/1.2/reference/classcrow_1_1json_1_1wvalue-members.html @@ -0,0 +1,186 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::json::wvalue Member List
+
+
+ +

This is the complete list of members for crow::json::wvalue, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
clear()crow::json::wvalueinline
content_type (defined in crow::returnable)crow::returnable
count(const std::string &str) const (defined in crow::json::wvalue)crow::json::wvalueinline
crow::mustache::template_t (defined in crow::json::wvalue)crow::json::wvaluefriend
dump(const int indent, const char separator=' ') const (defined in crow::json::wvalue)crow::json::wvalueinline
dump() const (defined in crow::json::wvalue)crow::json::wvalueinlinevirtual
empty_object()crow::json::wvalueinlinestatic
estimate_length() constcrow::json::wvalueinline
execute(std::string txt="") const (defined in crow::json::wvalue)crow::json::wvalueinline
keys() const (defined in crow::json::wvalue)crow::json::wvalueinline
list typedef (defined in crow::json::wvalue)crow::json::wvalue
object typedef (defined in crow::json::wvalue)crow::json::wvalue
operator=(wvalue &&r) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(std::nullptr_t) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(bool value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(float value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(double value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(unsigned short value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(short value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(long long value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(long value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(int value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(unsigned long long value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(unsigned long value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(unsigned int value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(const char *str) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(const std::string &str) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(list &&v) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(const std::vector< T > &v) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(std::initializer_list< std::pair< std::string const, wvalue >> initializer_list) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(object const &value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(object &&value) (defined in crow::json::wvalue)crow::json::wvalueinline
operator=(std::function< std::string(std::string &)> &&func) (defined in crow::json::wvalue)crow::json::wvalueinline
operator[](unsigned index) (defined in crow::json::wvalue)crow::json::wvalueinline
operator[](unsigned index) const (defined in crow::json::wvalue)crow::json::wvalueinline
operator[](const std::string &str) (defined in crow::json::wvalue)crow::json::wvalueinline
operator[](const std::string &str) const (defined in crow::json::wvalue)crow::json::wvalueinline
reset() (defined in crow::json::wvalue)crow::json::wvalueinline
returnable(std::string ctype) (defined in crow::returnable)crow::returnableinline
size() constcrow::json::wvalueinline
t() const (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue() (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::nullptr_t) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(bool value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::uint8_t value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::uint16_t value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::uint32_t value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::uint64_t value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::int8_t value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::int16_t value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::int32_t value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::int64_t value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(float value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(double value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(char const *value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::string const &value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::string &&value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(std::initializer_list< std::pair< std::string const, wvalue >> initializer_list) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(object const &value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(object &&value) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(const list &r) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(list &r) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(const rvalue &r)crow::json::wvalueinline
wvalue(const wvalue &r) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue(wvalue &&r) (defined in crow::json::wvalue)crow::json::wvalueinline
wvalue_reader (defined in crow::json::wvalue)crow::json::wvaluefriend
~returnable() (defined in crow::returnable)crow::returnableinlinevirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1json_1_1wvalue.html b/1.2/reference/classcrow_1_1json_1_1wvalue.html new file mode 100644 index 000000000..9a8c9b31d --- /dev/null +++ b/1.2/reference/classcrow_1_1json_1_1wvalue.html @@ -0,0 +1,364 @@ + + + + + + + + Crow: crow::json::wvalue Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ + +
+ +

JSON write value. + More...

+ +

#include <json.h>

+
+Inheritance diagram for crow::json::wvalue:
+
+
+ + +crow::returnable + +
+ + + + + + +

+Public Types

+using object = std::unordered_map< std::string, wvalue >
 
+using list = std::vector< wvalue >
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

+type t () const
 
wvalue (std::nullptr_t)
 
wvalue (bool value)
 
wvalue (std::uint8_t value)
 
wvalue (std::uint16_t value)
 
wvalue (std::uint32_t value)
 
wvalue (std::uint64_t value)
 
wvalue (std::int8_t value)
 
wvalue (std::int16_t value)
 
wvalue (std::int32_t value)
 
wvalue (std::int64_t value)
 
wvalue (float value)
 
wvalue (double value)
 
wvalue (char const *value)
 
wvalue (std::string const &value)
 
wvalue (std::string &&value)
 
wvalue (std::initializer_list< std::pair< std::string const, wvalue >> initializer_list)
 
wvalue (object const &value)
 
wvalue (object &&value)
 
wvalue (const list &r)
 
wvalue (list &r)
 
wvalue (const rvalue &r)
 Create a write value from a read value (useful for editing JSON strings).
 
wvalue (const wvalue &r)
 
wvalue (wvalue &&r)
 
+wvalueoperator= (wvalue &&r)
 
+void clear ()
 Used for compatibility, same as reset()
 
+void reset ()
 
+wvalueoperator= (std::nullptr_t)
 
+wvalueoperator= (bool value)
 
+wvalueoperator= (float value)
 
+wvalueoperator= (double value)
 
+wvalueoperator= (unsigned short value)
 
+wvalueoperator= (short value)
 
+wvalueoperator= (long long value)
 
+wvalueoperator= (long value)
 
+wvalueoperator= (int value)
 
+wvalueoperator= (unsigned long long value)
 
+wvalueoperator= (unsigned long value)
 
+wvalueoperator= (unsigned int value)
 
+wvalueoperator= (const char *str)
 
+wvalueoperator= (const std::string &str)
 
+wvalueoperator= (list &&v)
 
+template<typename T >
wvalueoperator= (const std::vector< T > &v)
 
+wvalueoperator= (std::initializer_list< std::pair< std::string const, wvalue >> initializer_list)
 
+wvalueoperator= (object const &value)
 
+wvalueoperator= (object &&value)
 
+wvalueoperator= (std::function< std::string(std::string &)> &&func)
 
+wvalueoperator[] (unsigned index)
 
+const wvalueoperator[] (unsigned index) const
 
+int count (const std::string &str) const
 
+wvalueoperator[] (const std::string &str)
 
+const wvalueoperator[] (const std::string &str) const
 
+std::vector< std::string > keys () const
 
+std::string execute (std::string txt="") const
 
+std::size_t size () const
 If the wvalue is a list, it returns the length of the list, otherwise it returns 1.
 
+size_t estimate_length () const
 Returns an estimated size of the value in bytes.
 
+std::string dump (const int indent, const char separator=' ') const
 
+std::string dump () const
 
- Public Member Functions inherited from crow::returnable
returnable (std::string ctype)
 
+ + + + +

+Static Public Member Functions

+static crow::json::wvalue empty_object ()
 Create an empty json value (outputs "{}" instead of a "null" string)
 
+ + + + + +

+Friends

+class crow::mustache::template_t
 
+struct wvalue_reader
 
+ + + + +

+Additional Inherited Members

- Public Attributes inherited from crow::returnable
+std::string content_type
 
+

Detailed Description

+

JSON write value.

+

Value can mean any json value, including a JSON object.
+ Write means this class is used to primarily assemble JSON objects using keys and values and export those into a string.

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1json_1_1wvalue.js b/1.2/reference/classcrow_1_1json_1_1wvalue.js new file mode 100644 index 000000000..8d2d5b76d --- /dev/null +++ b/1.2/reference/classcrow_1_1json_1_1wvalue.js @@ -0,0 +1,66 @@ +var classcrow_1_1json_1_1wvalue = +[ + [ "list", "classcrow_1_1json_1_1wvalue.html#a4a885b86093c6fc423747a46865996b3", null ], + [ "object", "classcrow_1_1json_1_1wvalue.html#aaa67583404db6c3f8f0d28783996887a", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a3bd09f79662afa14d7da1016e0da672d", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#adba131461d1badd64d0b07f38699a3be", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#aa4321a6e809cbf5a3100905e963ce43b", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a831735838c1dd18fbcb208d8e31841f3", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a69aa995526ba24ca17d8dec78e74cc01", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a8b3669a45284129d59d9cbb8b808675a", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a061b3e7466d89b73c4f5a36ea43e1a7e", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#ae11a92a4f940ed9094b4f317a3d1c53d", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a85cbaee18c9781f1beb08e8c8891f42d", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a229d00b0df6b6587b7e38e6837664c62", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a3da3a0a2c7792073a83ea21a41825915", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a419c1bd3fdf09d6209ce24193fcb0a8b", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a0968eb441e5518fde53840f5eb9f23ee", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a4c08ffc1579c0c3cfeb729889e8a618e", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a07e7f9291eef0ba80ba5bdbd02cfd0ba", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#adb29b055d9654697f6f60c65141dd4a1", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a7b27cf8c76058972391014f0f9fa3c4b", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#af2b309cba1e3af1ad1c288de94cdeb55", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a10971407ce42243530c4cec2869788e0", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#ac2cff8bc7cf17dff6ecb87100f938e5a", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#ade7cb4f77f8226d0956a0668f459b7e3", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a1813a29de56af96789cc76b8cdb0dbbe", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a9aa686c7631dd551f121bb91d5f07d2b", null ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html#a780a992b87a23470b99ef4b594ffd1ba", null ], + [ "clear", "classcrow_1_1json_1_1wvalue.html#af46596998d8e639a23b401e951297b63", null ], + [ "count", "classcrow_1_1json_1_1wvalue.html#ade9b70f37264daab1b7992061eb526bd", null ], + [ "dump", "classcrow_1_1json_1_1wvalue.html#a41566541702d2737cb48c907a4408750", null ], + [ "dump", "classcrow_1_1json_1_1wvalue.html#a753963d3cda61a5845d0926f5e99398c", null ], + [ "estimate_length", "classcrow_1_1json_1_1wvalue.html#a5af23d208ed3d066a0fb5339350978c6", null ], + [ "execute", "classcrow_1_1json_1_1wvalue.html#a50ef41d802ec0fb48c407fbc0194e70a", null ], + [ "keys", "classcrow_1_1json_1_1wvalue.html#aa7519105cd7878322ecef8536fdead7e", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#abda777617312d286b38f489055cf7907", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a1d3096d01b23f42b64da2d89be942ccd", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#aee7c185b7984ce7cd39567580d44dc3e", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a59bab9796cae55bab5350ee8ee47676a", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a5571fb38b397935150885ff7960a6ac6", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a10981d0d4b6c3773a32a172e8820a8af", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#aad8380b24617a991d0afd81993c11b12", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a2d9cf8c7ef5676469cd98f7af50a600d", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a80b6297e11ab7dfa3ca9819281cd337d", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#ae2dad9fd35a182860051ca51547d1c59", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a928740e05daf3017fea95e2db70ec04e", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a60871591b1b0d88555c0d8d7a720dd7b", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a387243a191d80d728338bd1105812762", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a4f1583fcfdf83bb50a39a17c0316f186", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a83d2b3dfd8f9349e902e02faf15fd0c2", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a8e901650c163d7ae0c1359931d578ca2", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a368fededb881ece77bcb97d024ebb334", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#ae49edd4dc612cfb374ac7d9173066e62", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#a0c2fa8d4a3d4df8b6f773710dd0cd10f", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#ab1ef13ccac07c1b858e7f6be24274e64", null ], + [ "operator=", "classcrow_1_1json_1_1wvalue.html#aaafb5db799a2eff74cfcaddd87ebe053", null ], + [ "operator[]", "classcrow_1_1json_1_1wvalue.html#a75a106571d5ae1b9be6903f8e2435754", null ], + [ "operator[]", "classcrow_1_1json_1_1wvalue.html#a75834fd2be941a3e6c71b1c56ba21e76", null ], + [ "operator[]", "classcrow_1_1json_1_1wvalue.html#ae0d1876f5cd3f8ac5b61970d12b0ad74", null ], + [ "operator[]", "classcrow_1_1json_1_1wvalue.html#aa5e09c1bf6e86b06e7998e5d6ce4a08b", null ], + [ "reset", "classcrow_1_1json_1_1wvalue.html#ab13538ab6037cf427ed225b94d703ce9", null ], + [ "size", "classcrow_1_1json_1_1wvalue.html#a1ded929c63fcb6e3c53be38e9b54c672", null ], + [ "t", "classcrow_1_1json_1_1wvalue.html#a2e8d3ed2849f16bb1894c4d48cb49921", null ], + [ "crow::mustache::template_t", "classcrow_1_1json_1_1wvalue.html#aedfa8358796846a88c67b51d3b280461", null ], + [ "wvalue_reader", "classcrow_1_1json_1_1wvalue.html#a2cf98ec966c306206e0d2d359bb561df", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1json_1_1wvalue.png b/1.2/reference/classcrow_1_1json_1_1wvalue.png new file mode 100644 index 000000000..0eab4ab53 Binary files /dev/null and b/1.2/reference/classcrow_1_1json_1_1wvalue.png differ diff --git a/1.2/reference/classcrow_1_1logger-members.html b/1.2/reference/classcrow_1_1logger-members.html new file mode 100644 index 000000000..ca4988350 --- /dev/null +++ b/1.2/reference/classcrow_1_1logger-members.html @@ -0,0 +1,125 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::logger Member List
+
+
+ +

This is the complete list of members for crow::logger, including all inherited members.

+ + + + + + + +
get_current_log_level() (defined in crow::logger)crow::loggerinlinestatic
logger(LogLevel level) (defined in crow::logger)crow::loggerinline
operator<<(T const &value) (defined in crow::logger)crow::loggerinline
setHandler(ILogHandler *handler) (defined in crow::logger)crow::loggerinlinestatic
setLogLevel(LogLevel level) (defined in crow::logger)crow::loggerinlinestatic
~logger() (defined in crow::logger)crow::loggerinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1logger.html b/1.2/reference/classcrow_1_1logger.html new file mode 100644 index 000000000..a74116327 --- /dev/null +++ b/1.2/reference/classcrow_1_1logger.html @@ -0,0 +1,147 @@ + + + + + + + + Crow: crow::logger Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ + +
+ + + + + + + +

+Public Member Functions

logger (LogLevel level)
 
+template<typename T >
loggeroperator<< (T const &value)
 
+ + + + + + + +

+Static Public Member Functions

+static void setLogLevel (LogLevel level)
 
+static void setHandler (ILogHandler *handler)
 
+static LogLevel get_current_log_level ()
 
+
The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1logger.js b/1.2/reference/classcrow_1_1logger.js new file mode 100644 index 000000000..e10abe236 --- /dev/null +++ b/1.2/reference/classcrow_1_1logger.js @@ -0,0 +1,6 @@ +var classcrow_1_1logger = +[ + [ "logger", "classcrow_1_1logger.html#a1e8d38b6f23b020c5c008b0028210acc", null ], + [ "~logger", "classcrow_1_1logger.html#a59b838e541514c082a01e9111c5a11f6", null ], + [ "operator<<", "classcrow_1_1logger.html#a854e9da406195e08aa7712c7d4ca27d0", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception-members.html b/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception-members.html new file mode 100644 index 000000000..e60c65bd3 --- /dev/null +++ b/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception-members.html @@ -0,0 +1,122 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::mustache::invalid_template_exception Member List
+
+
+ +

This is the complete list of members for crow::mustache::invalid_template_exception, including all inherited members.

+ + + + +
invalid_template_exception(const std::string &msg) (defined in crow::mustache::invalid_template_exception)crow::mustache::invalid_template_exceptioninline
msg (defined in crow::mustache::invalid_template_exception)crow::mustache::invalid_template_exception
what() const (defined in crow::mustache::invalid_template_exception)crow::mustache::invalid_template_exceptioninlinevirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception.html b/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception.html new file mode 100644 index 000000000..483060beb --- /dev/null +++ b/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception.html @@ -0,0 +1,146 @@ + + + + + + + + Crow: crow::mustache::invalid_template_exception Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::mustache::invalid_template_exception Class Reference
+
+
+
+Inheritance diagram for crow::mustache::invalid_template_exception:
+
+
+ +
+ + + + + + +

+Public Member Functions

invalid_template_exception (const std::string &msg)
 
+virtual const char * what () const throw ()
 
+ + + +

+Public Attributes

+std::string msg
 
+
The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception.js b/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception.js new file mode 100644 index 000000000..17c9c27f6 --- /dev/null +++ b/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception.js @@ -0,0 +1,6 @@ +var classcrow_1_1mustache_1_1invalid__template__exception = +[ + [ "invalid_template_exception", "classcrow_1_1mustache_1_1invalid__template__exception.html#a2a598ed4d91525b8642ec0c0c4b711a9", null ], + [ "what", "classcrow_1_1mustache_1_1invalid__template__exception.html#afe324639897b33eeda550fc4e3ecc34e", null ], + [ "msg", "classcrow_1_1mustache_1_1invalid__template__exception.html#a6ec8bc8b03e34a5d2443d2f080e9b739", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception.png b/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception.png new file mode 100644 index 000000000..c552c965e Binary files /dev/null and b/1.2/reference/classcrow_1_1mustache_1_1invalid__template__exception.png differ diff --git a/1.2/reference/classcrow_1_1mustache_1_1template__t-members.html b/1.2/reference/classcrow_1_1mustache_1_1template__t-members.html new file mode 100644 index 000000000..6f9b02867 --- /dev/null +++ b/1.2/reference/classcrow_1_1mustache_1_1template__t-members.html @@ -0,0 +1,125 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::mustache::template_t Member List
+
+
+ +

This is the complete list of members for crow::mustache::template_t, including all inherited members.

+ + + + + + + +
render() constcrow::mustache::template_tinline
render(const context &ctx) constcrow::mustache::template_tinline
render(const context &&ctx) constcrow::mustache::template_tinline
render_string() constcrow::mustache::template_tinline
render_string(const context &ctx) constcrow::mustache::template_tinline
template_t(std::string body) (defined in crow::mustache::template_t)crow::mustache::template_tinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1mustache_1_1template__t.html b/1.2/reference/classcrow_1_1mustache_1_1template__t.html new file mode 100644 index 000000000..c0268968b --- /dev/null +++ b/1.2/reference/classcrow_1_1mustache_1_1template__t.html @@ -0,0 +1,157 @@ + + + + + + + + Crow: crow::mustache::template_t Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::mustache::template_t Class Reference
+
+
+ +

A mustache template object. + More...

+ +

#include <mustache.h>

+ + + + + + + + + + + + + + + + + + + +

+Public Member Functions

template_t (std::string body)
 
+rendered_template render () const
 Output a returnable template from this mustache template.
 
+rendered_template render (const context &ctx) const
 Apply the values from the context provided and output a returnable template from this mustache template.
 
+rendered_template render (const context &&ctx) const
 Apply the values from the context provided and output a returnable template from this mustache template.
 
+std::string render_string () const
 Output a returnable template from this mustache template.
 
+std::string render_string (const context &ctx) const
 Apply the values from the context provided and output a returnable template from this mustache template.
 
+

Detailed Description

+

A mustache template object.

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1mustache_1_1template__t.js b/1.2/reference/classcrow_1_1mustache_1_1template__t.js new file mode 100644 index 000000000..a82274cc8 --- /dev/null +++ b/1.2/reference/classcrow_1_1mustache_1_1template__t.js @@ -0,0 +1,9 @@ +var classcrow_1_1mustache_1_1template__t = +[ + [ "template_t", "classcrow_1_1mustache_1_1template__t.html#a8c37d92fba8f0a4cf4d4f7a254847ccc", null ], + [ "render", "classcrow_1_1mustache_1_1template__t.html#a67caf7e23349a829b913c897ab882a8e", null ], + [ "render", "classcrow_1_1mustache_1_1template__t.html#ae8f2561efe590c0b5704df76b0c82aa5", null ], + [ "render", "classcrow_1_1mustache_1_1template__t.html#a77c579b71240695bd9fb634f48facd03", null ], + [ "render_string", "classcrow_1_1mustache_1_1template__t.html#a21199e08a066d7c66b5728354c2c40fd", null ], + [ "render_string", "classcrow_1_1mustache_1_1template__t.html#af2258136c497b02eadfacbf50704de08", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1query__string-members.html b/1.2/reference/classcrow_1_1query__string-members.html new file mode 100644 index 000000000..4683d2c42 --- /dev/null +++ b/1.2/reference/classcrow_1_1query__string-members.html @@ -0,0 +1,134 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::query_string Member List
+
+
+ +

This is the complete list of members for crow::query_string, including all inherited members.

+ + + + + + + + + + + + + + + + +
clear() (defined in crow::query_string)crow::query_stringinline
get(const std::string &name) constcrow::query_stringinline
get_dict(const std::string &name) constcrow::query_stringinline
get_list(const std::string &name, bool use_brackets=true) constcrow::query_stringinline
keys() const (defined in crow::query_string)crow::query_stringinline
MAX_KEY_VALUE_PAIRS_COUNT (defined in crow::query_string)crow::query_stringstatic
operator<< (defined in crow::query_string)crow::query_stringfriend
operator=(const query_string &qs) (defined in crow::query_string)crow::query_stringinline
operator=(query_string &&qs) noexcept (defined in crow::query_string)crow::query_stringinline
pop(const std::string &name)crow::query_stringinline
pop_dict(const std::string &name)crow::query_stringinline
pop_list(const std::string &name, bool use_brackets=true)crow::query_stringinline
query_string()=default (defined in crow::query_string)crow::query_string
query_string(const query_string &qs) (defined in crow::query_string)crow::query_stringinline
query_string(std::string params, bool url=true) (defined in crow::query_string)crow::query_stringinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1query__string.html b/1.2/reference/classcrow_1_1query__string.html new file mode 100644 index 000000000..60bdd5d85 --- /dev/null +++ b/1.2/reference/classcrow_1_1query__string.html @@ -0,0 +1,286 @@ + + + + + + + + Crow: crow::query_string Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::query_string Class Reference
+
+
+ +

A class to represent any data coming after the ? in the request URL into key-value pairs. + More...

+ +

#include <query_string.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

query_string (const query_string &qs)
 
+query_stringoperator= (const query_string &qs)
 
+query_stringoperator= (query_string &&qs) noexcept
 
query_string (std::string params, bool url=true)
 
+void clear ()
 
char * get (const std::string &name) const
 Get a value from a name, used for ?name=value. More...
 
+char * pop (const std::string &name)
 Works similar to get() except it removes the item from the query string.
 
std::vector< char * > get_list (const std::string &name, bool use_brackets=true) const
 Returns a list of values, passed as ?name[]=value1&name[]=value2&...name[]=valuen with n being the size of the list. More...
 
+std::vector< char * > pop_list (const std::string &name, bool use_brackets=true)
 Similar to get_list() but it removes the.
 
std::unordered_map< std::string, std::string > get_dict (const std::string &name) const
 Works similar to get_list() except the brackets are mandatory must not be empty. More...
 
+std::unordered_map< std::string, std::string > pop_dict (const std::string &name)
 Works the same as get_dict() but removes the values from the query string.
 
+std::vector< std::string > keys () const
 
+ + + +

+Static Public Attributes

+static const int MAX_KEY_VALUE_PAIRS_COUNT = 256
 
+ + + +

+Friends

+std::ostream & operator<< (std::ostream &os, const query_string &qs)
 
+

Detailed Description

+

A class to represent any data coming after the ? in the request URL into key-value pairs.

+

Member Function Documentation

+ +

◆ get()

+ +
+
+ + + + + +
+ + + + + + + + +
char* crow::query_string::get (const std::string & name) const
+
+inline
+
+ +

Get a value from a name, used for ?name=value.

+

Note: this method returns the value of the first occurrence of the key only, to return all occurrences, see get_list().

+ +
+
+ +

◆ get_dict()

+ +
+
+ + + + + +
+ + + + + + + + +
std::unordered_map<std::string, std::string> crow::query_string::get_dict (const std::string & name) const
+
+inline
+
+ +

Works similar to get_list() except the brackets are mandatory must not be empty.

+

For example calling get_dict(yourname) on ?yourname[sub1]=42&yourname[sub2]=84 would give a map containing {sub1 : 42, sub2 : 84}.

+

if your query string has both empty brackets and ones with a key inside, use pop_list() to get all the values without a key before running this method.

+ +
+
+ +

◆ get_list()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
std::vector<char*> crow::query_string::get_list (const std::string & name,
bool use_brackets = true 
) const
+
+inline
+
+ +

Returns a list of values, passed as ?name[]=value1&name[]=value2&...name[]=valuen with n being the size of the list.

+

Note: Square brackets in the above example are controlled by use_brackets boolean (true by default). If set to false, the example becomes ?name=value1,name=value2...name=valuen

+ +
+
+
The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1query__string.js b/1.2/reference/classcrow_1_1query__string.js new file mode 100644 index 000000000..5fab89a77 --- /dev/null +++ b/1.2/reference/classcrow_1_1query__string.js @@ -0,0 +1,17 @@ +var classcrow_1_1query__string = +[ + [ "query_string", "classcrow_1_1query__string.html#a34567d87bd0889fab4089241bad6fce5", null ], + [ "query_string", "classcrow_1_1query__string.html#a37aa44f47830f12290364cc0afd94ad2", null ], + [ "query_string", "classcrow_1_1query__string.html#a22b3133693d0daa5cb9647f4a5908f62", null ], + [ "clear", "classcrow_1_1query__string.html#a19138a2e29bba49996bf67e7403da405", null ], + [ "get", "classcrow_1_1query__string.html#a7db05380bed403b88cb2fe6a5fdd8d75", null ], + [ "get_dict", "classcrow_1_1query__string.html#af56add12ca6a7f0222956e353d1d40bb", null ], + [ "get_list", "classcrow_1_1query__string.html#a657e5fe435375cd31229944ed2ad5608", null ], + [ "keys", "classcrow_1_1query__string.html#ad83b800ef5b122d361061d9d5f889dd9", null ], + [ "operator=", "classcrow_1_1query__string.html#a649427bd73c23963eaa29dc230a5cde0", null ], + [ "operator=", "classcrow_1_1query__string.html#aec8c83455de1a146999d8e8d2ecbe3bf", null ], + [ "pop", "classcrow_1_1query__string.html#ab0a81b08a5531b98c08b1a6a268ebea1", null ], + [ "pop_dict", "classcrow_1_1query__string.html#a0744b06ff0709ebbe7c2a1646564508b", null ], + [ "pop_list", "classcrow_1_1query__string.html#a8ef1a91122dc53e1235919e107fd1a9c", null ], + [ "operator<<", "classcrow_1_1query__string.html#a43f85a8b06660b61cd05226504559768", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1websocket_1_1_connection-members.html b/1.2/reference/classcrow_1_1websocket_1_1_connection-members.html new file mode 100644 index 000000000..8e8b912ce --- /dev/null +++ b/1.2/reference/classcrow_1_1websocket_1_1_connection-members.html @@ -0,0 +1,143 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::websocket::Connection< Adaptor, Handler > Member List
+
+
+ +

This is the complete list of members for crow::websocket::Connection< Adaptor, Handler >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
build_header(int opcode, size_t size)crow::websocket::Connection< Adaptor, Handler >inlineprotected
check_destroy()crow::websocket::Connection< Adaptor, Handler >inlineprotected
close(std::string const &msg) overridecrow::websocket::Connection< Adaptor, Handler >inlinevirtual
Connection(const crow::request &req, Adaptor &&adaptor, Handler *handler, uint64_t max_payload, std::function< void(crow::websocket::connection &)> open_handler, std::function< void(crow::websocket::connection &, const std::string &, bool)> message_handler, std::function< void(crow::websocket::connection &, const std::string &)> close_handler, std::function< void(crow::websocket::connection &, const std::string &)> error_handler, std::function< bool(const crow::request &, void **)> accept_handler)crow::websocket::Connection< Adaptor, Handler >inline
dispatch(CompletionHandler &&handler)crow::websocket::Connection< Adaptor, Handler >inline
do_read()crow::websocket::Connection< Adaptor, Handler >inlineprotected
do_write()crow::websocket::Connection< Adaptor, Handler >inlineprotected
get_remote_ip() override (defined in crow::websocket::Connection< Adaptor, Handler >)crow::websocket::Connection< Adaptor, Handler >inlinevirtual
handle_fragment()crow::websocket::Connection< Adaptor, Handler >inlineprotected
is_FIN()crow::websocket::Connection< Adaptor, Handler >inlineprotected
opcode()crow::websocket::Connection< Adaptor, Handler >inlineprotected
post(CompletionHandler &&handler)crow::websocket::Connection< Adaptor, Handler >inline
send_binary(std::string msg) overridecrow::websocket::Connection< Adaptor, Handler >inlinevirtual
send_data(int opcode, std::string &&msg) (defined in crow::websocket::Connection< Adaptor, Handler >)crow::websocket::Connection< Adaptor, Handler >inlineprotected
send_data_impl(SendMessageType *s) (defined in crow::websocket::Connection< Adaptor, Handler >)crow::websocket::Connection< Adaptor, Handler >inlineprotected
send_ping(std::string msg) overridecrow::websocket::Connection< Adaptor, Handler >inlinevirtual
send_pong(std::string msg) overridecrow::websocket::Connection< Adaptor, Handler >inlinevirtual
send_text(std::string msg) overridecrow::websocket::Connection< Adaptor, Handler >inlinevirtual
set_max_payload_size(uint64_t payload) (defined in crow::websocket::Connection< Adaptor, Handler >)crow::websocket::Connection< Adaptor, Handler >inline
start(std::string &&hello)crow::websocket::Connection< Adaptor, Handler >inlineprotected
userdata(void *u) (defined in crow::websocket::connection)crow::websocket::connectioninline
userdata() (defined in crow::websocket::connection)crow::websocket::connectioninline
~Connection() noexcept override (defined in crow::websocket::Connection< Adaptor, Handler >)crow::websocket::Connection< Adaptor, Handler >inline
~connection()=default (defined in crow::websocket::connection)crow::websocket::connectionvirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1websocket_1_1_connection.html b/1.2/reference/classcrow_1_1websocket_1_1_connection.html new file mode 100644 index 000000000..f3d2193dc --- /dev/null +++ b/1.2/reference/classcrow_1_1websocket_1_1_connection.html @@ -0,0 +1,545 @@ + + + + + + + + Crow: crow::websocket::Connection< Adaptor, Handler > Class Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::websocket::Connection< Adaptor, Handler > Class Template Reference
+
+
+ +

A websocket connection. + More...

+ +

#include <websocket.h>

+
+Inheritance diagram for crow::websocket::Connection< Adaptor, Handler >:
+
+
+ + +crow::websocket::connection + +
+ + + + + + +

+Classes

struct  SendMessageType
 
struct  WeakWrappedMessage
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 Connection (const crow::request &req, Adaptor &&adaptor, Handler *handler, uint64_t max_payload, std::function< void(crow::websocket::connection &)> open_handler, std::function< void(crow::websocket::connection &, const std::string &, bool)> message_handler, std::function< void(crow::websocket::connection &, const std::string &)> close_handler, std::function< void(crow::websocket::connection &, const std::string &)> error_handler, std::function< bool(const crow::request &, void **)> accept_handler)
 Constructor for a connection. More...
 
+template<typename CompletionHandler >
void dispatch (CompletionHandler &&handler)
 Send data through the socket.
 
+template<typename CompletionHandler >
void post (CompletionHandler &&handler)
 Send data through the socket and return immediately.
 
void send_ping (std::string msg) override
 Send a "Ping" message. More...
 
void send_pong (std::string msg) override
 Send a "Pong" message. More...
 
+void send_binary (std::string msg) override
 Send a binary encoded message.
 
+void send_text (std::string msg) override
 Send a plaintext message.
 
void close (std::string const &msg) override
 Send a close signal. More...
 
+std::string get_remote_ip () override
 
+void set_max_payload_size (uint64_t payload)
 
- Public Member Functions inherited from crow::websocket::connection
+void userdata (void *u)
 
+void * userdata ()
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Protected Member Functions

+std::string build_header (int opcode, size_t size)
 Generate the websocket headers using an opcode and the message size (in bytes).
 
void start (std::string &&hello)
 Send the HTTP upgrade response. More...
 
void do_read ()
 Read a websocket message. More...
 
+bool is_FIN ()
 Check if the FIN bit is set.
 
+int opcode ()
 Extract the opcode from the header.
 
bool handle_fragment ()
 Process the payload fragment. More...
 
void do_write ()
 Send the buffers' data through the socket. More...
 
+void check_destroy ()
 Destroy the Connection.
 
+void send_data_impl (SendMessageType *s)
 
+void send_data (int opcode, std::string &&msg)
 
+

Detailed Description

+

template<typename Adaptor, typename Handler>
+class crow::websocket::Connection< Adaptor, Handler >

+ +

A websocket connection.

+

Constructor & Destructor Documentation

+ +

◆ Connection()

+ +
+
+
+template<typename Adaptor , typename Handler >
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
crow::websocket::Connection< Adaptor, Handler >::Connection (const crow::requestreq,
Adaptor && adaptor,
Handler * handler,
uint64_t max_payload,
std::function< void(crow::websocket::connection &)> open_handler,
std::function< void(crow::websocket::connection &, const std::string &, bool)> message_handler,
std::function< void(crow::websocket::connection &, const std::string &)> close_handler,
std::function< void(crow::websocket::connection &, const std::string &)> error_handler,
std::function< bool(const crow::request &, void **)> accept_handler 
)
+
+inline
+
+ +

Constructor for a connection.

+

Requires a request with an "Upgrade: websocket" header.
+ Automatically handles the handshake.

+ +
+
+

Member Function Documentation

+ +

◆ close()

+ +
+
+
+template<typename Adaptor , typename Handler >
+ + + + + +
+ + + + + + + + +
void crow::websocket::Connection< Adaptor, Handler >::close (std::string const & msg)
+
+inlineoverridevirtual
+
+ +

Send a close signal.

+

Sets a flag to destroy the object once the message is sent.

+ +

Implements crow::websocket::connection.

+ +
+
+ +

◆ do_read()

+ +
+
+
+template<typename Adaptor , typename Handler >
+ + + + + +
+ + + + + + + +
void crow::websocket::Connection< Adaptor, Handler >::do_read ()
+
+inlineprotected
+
+ +

Read a websocket message.

+

Involves:
+ Handling headers (opcodes, size).
+ Unmasking the payload.
+ Reading the actual payload.
+

+ +
+
+ +

◆ do_write()

+ +
+
+
+template<typename Adaptor , typename Handler >
+ + + + + +
+ + + + + + + +
void crow::websocket::Connection< Adaptor, Handler >::do_write ()
+
+inlineprotected
+
+ +

Send the buffers' data through the socket.

+

Also destroys the object if the Close flag is set.

+ +
+
+ +

◆ handle_fragment()

+ +
+
+
+template<typename Adaptor , typename Handler >
+ + + + + +
+ + + + + + + +
bool crow::websocket::Connection< Adaptor, Handler >::handle_fragment ()
+
+inlineprotected
+
+ +

Process the payload fragment.

+

Unmasks the fragment, checks the opcode, merges fragments into 1 message body, and calls the appropriate handler.

+ +
+
+ +

◆ send_ping()

+ +
+
+
+template<typename Adaptor , typename Handler >
+ + + + + +
+ + + + + + + + +
void crow::websocket::Connection< Adaptor, Handler >::send_ping (std::string msg)
+
+inlineoverridevirtual
+
+ +

Send a "Ping" message.

+

Usually invoked to check if the other point is still online.

+ +

Implements crow::websocket::connection.

+ +
+
+ +

◆ send_pong()

+ +
+
+
+template<typename Adaptor , typename Handler >
+ + + + + +
+ + + + + + + + +
void crow::websocket::Connection< Adaptor, Handler >::send_pong (std::string msg)
+
+inlineoverridevirtual
+
+ +

Send a "Pong" message.

+

Usually automatically invoked as a response to a "Ping" message.

+ +

Implements crow::websocket::connection.

+ +
+
+ +

◆ start()

+ +
+
+
+template<typename Adaptor , typename Handler >
+ + + + + +
+ + + + + + + + +
void crow::websocket::Connection< Adaptor, Handler >::start (std::string && hello)
+
+inlineprotected
+
+ +

Send the HTTP upgrade response.

+

Finishes the handshake process, then starts reading messages from the socket.

+ +
+
+
The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1websocket_1_1_connection.js b/1.2/reference/classcrow_1_1websocket_1_1_connection.js new file mode 100644 index 000000000..07d8dd4b0 --- /dev/null +++ b/1.2/reference/classcrow_1_1websocket_1_1_connection.js @@ -0,0 +1,26 @@ +var classcrow_1_1websocket_1_1_connection = +[ + [ "SendMessageType", "structcrow_1_1websocket_1_1_connection_1_1_send_message_type.html", "structcrow_1_1websocket_1_1_connection_1_1_send_message_type" ], + [ "WeakWrappedMessage", "structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.html", "structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message" ], + [ "Connection", "classcrow_1_1websocket_1_1_connection.html#ae13084d8ea772f54bf3397a9fab107d8", null ], + [ "~Connection", "classcrow_1_1websocket_1_1_connection.html#a0f9b68f4ac5b2b1af3bf721383244863", null ], + [ "build_header", "classcrow_1_1websocket_1_1_connection.html#a2fc995281b9452b56f743294baa7ed17", null ], + [ "check_destroy", "classcrow_1_1websocket_1_1_connection.html#a8030e7ca3e9ee5d07ccf7f8cb43fa317", null ], + [ "close", "classcrow_1_1websocket_1_1_connection.html#a663d3f3917b8cc7f9b54e6c7dfc8d604", null ], + [ "dispatch", "classcrow_1_1websocket_1_1_connection.html#a0d7758d7d22d74ee9ed17c8c7df0a380", null ], + [ "do_read", "classcrow_1_1websocket_1_1_connection.html#a1049d7689f068379e98954bfb04bee5c", null ], + [ "do_write", "classcrow_1_1websocket_1_1_connection.html#a787dde96965bf30d994bbc5fb3388281", null ], + [ "get_remote_ip", "classcrow_1_1websocket_1_1_connection.html#ae6b8882caf42fc65295920e064e83ecc", null ], + [ "handle_fragment", "classcrow_1_1websocket_1_1_connection.html#a292002f44552e5eabd8dd65f476a4c28", null ], + [ "is_FIN", "classcrow_1_1websocket_1_1_connection.html#a98f4af4eac4b807f970667b0147869a4", null ], + [ "opcode", "classcrow_1_1websocket_1_1_connection.html#a6d74305323202dc7ebd07cbd3ee19f98", null ], + [ "post", "classcrow_1_1websocket_1_1_connection.html#ae55db4104d46350f5a9e040d32600984", null ], + [ "send_binary", "classcrow_1_1websocket_1_1_connection.html#ac8ba4036c9777f0e3af3531791d8ca62", null ], + [ "send_data", "classcrow_1_1websocket_1_1_connection.html#ac27434329d97c1a7be8c2f649c180612", null ], + [ "send_data_impl", "classcrow_1_1websocket_1_1_connection.html#ad7f9fc603b168908dba35e4a82dce69b", null ], + [ "send_ping", "classcrow_1_1websocket_1_1_connection.html#ab5c1387014e5fdc0e9ebbb8661be04da", null ], + [ "send_pong", "classcrow_1_1websocket_1_1_connection.html#a22c353583685e0e878813ab67333342c", null ], + [ "send_text", "classcrow_1_1websocket_1_1_connection.html#a595b84a3c7206d4923286ac863b45ffb", null ], + [ "set_max_payload_size", "classcrow_1_1websocket_1_1_connection.html#a74ca3df127a5c009920b3c5bb1ec3c81", null ], + [ "start", "classcrow_1_1websocket_1_1_connection.html#a928134640aa98a86f56a71735a41147a", null ] +]; \ No newline at end of file diff --git a/1.2/reference/classcrow_1_1websocket_1_1_connection.png b/1.2/reference/classcrow_1_1websocket_1_1_connection.png new file mode 100644 index 000000000..d0a1f8f5b Binary files /dev/null and b/1.2/reference/classcrow_1_1websocket_1_1_connection.png differ diff --git a/1.2/reference/classes.html b/1.2/reference/classes.html new file mode 100644 index 000000000..a724cfc2b --- /dev/null +++ b/1.2/reference/classes.html @@ -0,0 +1,176 @@ + + + + + + + + Crow: Class Index + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Class Index
+
+
+
A | B | C | D | E | F | G | H | I | L | M | N | P | Q | R | S | T | U | W
+
+
+
A
+
Action (crow::mustache)
+
+
B
+
BaseRule (crow)
Blueprint (crow)
+
+
C
+
CachedSession (crow::session)
call (crow::detail::routing_handler_call_helper)
call< F, NInt, NUint, NDouble, NString, black_magic::S< double, Args1... >, black_magic::S< Args2... > > (crow::detail::routing_handler_call_helper)
call< F, NInt, NUint, NDouble, NString, black_magic::S< int64_t, Args1... >, black_magic::S< Args2... > > (crow::detail::routing_handler_call_helper)
call< F, NInt, NUint, NDouble, NString, black_magic::S< std::string, Args1... >, black_magic::S< Args2... > > (crow::detail::routing_handler_call_helper)
call< F, NInt, NUint, NDouble, NString, black_magic::S< uint64_t, Args1... >, black_magic::S< Args2... > > (crow::detail::routing_handler_call_helper)
call< F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S< Args1... > > (crow::detail::routing_handler_call_helper)
call_pair (crow::detail::routing_handler_call_helper)
call_params (crow::detail::routing_handler_call_helper)
CatchallRule (crow)
CerrLogHandler (crow)
check_after_handle_arity_3 (crow::detail)
check_after_handle_arity_3_const (crow::detail)
check_before_handle_arity_3 (crow::detail)
check_before_handle_arity_3_const (crow::detail)
check_global_call_false (crow::detail)
ci_hash (crow)
ci_key_eq (crow)
Connection (crow)
connection (crow::websocket)
Connection (crow::websocket)
CookieParser::context (crow)
CORSHandler::context (crow)
context (crow::detail)
SessionMiddleware::context (crow)
UTF8::context (crow)
CookieParser::Cookie (crow)
CookieParser (crow)
CORSHandler (crow)
CORSRules (crow)
Crow (crow)
+
+
D
+
DynamicRule (crow)
+
+
E
+
ExpirationTracker (crow::session)
+
+
F
+
FileStore (crow)
+
+
G
+
check_after_handle_arity_3::get (crow::detail)
check_after_handle_arity_3_const::get (crow::detail)
check_before_handle_arity_3::get (crow::detail)
check_before_handle_arity_3_const::get (crow::detail)
check_global_call_false::get (crow::detail)
+
+
H
+
Wrapped::handler_type_helper (crow::detail::routing_handler_call_helper)
Wrapped::handler_type_helper< const request &, Args... > (crow::detail::routing_handler_call_helper)
Wrapped::handler_type_helper< const request &, response &, Args... > (crow::detail::routing_handler_call_helper)
header (crow::multipart)
http_parser (crow)
http_parser_settings (crow)
HTTPParser (crow)
+
+
I
+
ILocalMiddleware (crow)
ILogHandler (crow)
InMemoryStore (crow)
invalid_template_exception (crow::mustache)
is_after_handle_arity_3_impl (crow::detail)
is_before_handle_arity_3_impl (crow::detail)
is_middleware_global (crow::detail)
+
+
L
+
logger (crow)
+
+
M
+
message (crow::multipart)
middleware_call_criteria_dynamic (crow::detail)
middleware_call_criteria_dynamic< false > (crow::detail)
middleware_call_criteria_dynamic< true > (crow::detail)
middleware_call_criteria_only_global (crow::detail)
middleware_indices (crow::detail)
multi_value (crow::session)
+
+
N
+
Trie::Node (crow)
+
+
P
+
part (crow::multipart)
partial_context (crow::detail)
partial_context<> (crow::detail)
+
+
Q
+
query_string (crow)
+
+
R
+
r_string (crow::json::detail)
rendered_template (crow::mustache)
Wrapped::req_handler_wrapper (crow::detail::routing_handler_call_helper)
request (crow)
response (crow)
returnable (crow)
Router (crow)
routing_handle_result (crow)
RuleParameterTraits (crow)
rvalue (crow::json)
+
+
S
+
Connection::SendMessageType (crow::websocket)
Server (crow)
SessionMiddleware (crow)
SHA1 (sha1)
SocketAdaptor (crow)
SSLAdaptor (crow)
response::static_file_info (crow)
+
+
T
+
TaggedRule (crow)
task_timer (crow::detail)
template_t (crow::mustache)
Trie (crow)
+
+
U
+
UTF8 (crow)
+
+
W
+
Connection::WeakWrappedMessage (crow::websocket)
WebSocketRule (crow)
Wrapped (crow::detail::routing_handler_call_helper)
wvalue (crow::json)
wvalue_reader (crow::json)
+
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classsha1_1_1_s_h_a1-members.html b/1.2/reference/classsha1_1_1_s_h_a1-members.html new file mode 100644 index 000000000..06ff97479 --- /dev/null +++ b/1.2/reference/classsha1_1_1_s_h_a1-members.html @@ -0,0 +1,133 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
sha1::SHA1 Member List
+
+
+ +

This is the complete list of members for sha1::SHA1, including all inherited members.

+ + + + + + + + + + + + + + + +
digest32_t typedef (defined in sha1::SHA1)sha1::SHA1
digest8_t typedef (defined in sha1::SHA1)sha1::SHA1
getDigest(digest32_t digest) (defined in sha1::SHA1)sha1::SHA1inline
getDigestBytes(digest8_t digest) (defined in sha1::SHA1)sha1::SHA1inline
LeftRotate(uint32_t value, size_t count) (defined in sha1::SHA1)sha1::SHA1inlinestatic
operator=(const SHA1 &s) (defined in sha1::SHA1)sha1::SHA1inline
processBlock(const void *const start, const void *const end) (defined in sha1::SHA1)sha1::SHA1inline
processBlock() (defined in sha1::SHA1)sha1::SHA1inlineprotected
processByte(uint8_t octet) (defined in sha1::SHA1)sha1::SHA1inline
processBytes(const void *const data, size_t len) (defined in sha1::SHA1)sha1::SHA1inline
reset() (defined in sha1::SHA1)sha1::SHA1inline
SHA1() (defined in sha1::SHA1)sha1::SHA1inline
SHA1(const SHA1 &s) (defined in sha1::SHA1)sha1::SHA1inline
~SHA1() (defined in sha1::SHA1)sha1::SHA1inlinevirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classsha1_1_1_s_h_a1.html b/1.2/reference/classsha1_1_1_s_h_a1.html new file mode 100644 index 000000000..c28049a75 --- /dev/null +++ b/1.2/reference/classsha1_1_1_s_h_a1.html @@ -0,0 +1,182 @@ + + + + + + + + Crow: sha1::SHA1 Class Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ + +
+ +

A tiny SHA1 algorithm implementation used internally in the Crow server (specifically in crow/websocket.h). + More...

+ +

#include <TinySHA1.hpp>

+ + + + + + +

+Public Types

+typedef uint32_t digest32_t[5]
 
+typedef uint8_t digest8_t[20]
 
+ + + + + + + + + + + + + + + + + +

+Public Member Functions

SHA1 (const SHA1 &s)
 
+const SHA1operator= (const SHA1 &s)
 
+SHA1reset ()
 
+SHA1processByte (uint8_t octet)
 
+SHA1processBlock (const void *const start, const void *const end)
 
+SHA1processBytes (const void *const data, size_t len)
 
+const uint32_t * getDigest (digest32_t digest)
 
+const uint8_t * getDigestBytes (digest8_t digest)
 
+ + + +

+Static Public Member Functions

+static uint32_t LeftRotate (uint32_t value, size_t count)
 
+ + + +

+Protected Member Functions

+void processBlock ()
 
+

Detailed Description

+

A tiny SHA1 algorithm implementation used internally in the Crow server (specifically in crow/websocket.h).

+

The documentation for this class was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/classsha1_1_1_s_h_a1.js b/1.2/reference/classsha1_1_1_s_h_a1.js new file mode 100644 index 000000000..1973afaf3 --- /dev/null +++ b/1.2/reference/classsha1_1_1_s_h_a1.js @@ -0,0 +1,16 @@ +var classsha1_1_1_s_h_a1 = +[ + [ "digest32_t", "classsha1_1_1_s_h_a1.html#a15f384f39d235a8912d5042dc920595f", null ], + [ "digest8_t", "classsha1_1_1_s_h_a1.html#a62b6c7838c4cdcb81700a6cc64fde994", null ], + [ "SHA1", "classsha1_1_1_s_h_a1.html#a440d0c3f17da510418b678f4c9dcbdf2", null ], + [ "~SHA1", "classsha1_1_1_s_h_a1.html#a7103b57eb1f51a498a92c095b9c21392", null ], + [ "SHA1", "classsha1_1_1_s_h_a1.html#a1d63d04a7f146a42000e0a2a35314c6f", null ], + [ "getDigest", "classsha1_1_1_s_h_a1.html#a7a097712264451da60aa0f30096dd516", null ], + [ "getDigestBytes", "classsha1_1_1_s_h_a1.html#a4fd38b624cba611b65730a9e747c584e", null ], + [ "operator=", "classsha1_1_1_s_h_a1.html#ae8f2ccbee9a15968482057e0d03a4247", null ], + [ "processBlock", "classsha1_1_1_s_h_a1.html#af00112a350d5f1f67a9ac00a0fee6793", null ], + [ "processBlock", "classsha1_1_1_s_h_a1.html#af5e58568ad3bcaf91640c7fd5e448d85", null ], + [ "processByte", "classsha1_1_1_s_h_a1.html#a8f7edf8ccfea07f988d5f40c4b5c768b", null ], + [ "processBytes", "classsha1_1_1_s_h_a1.html#abf8a680503b98b8f773f98752e34dbca", null ], + [ "reset", "classsha1_1_1_s_h_a1.html#ae2f5530e5be0837e6a222a1f244cbe6d", null ] +]; \ No newline at end of file diff --git a/1.2/reference/closed.png b/1.2/reference/closed.png new file mode 100644 index 000000000..98cc2c909 Binary files /dev/null and b/1.2/reference/closed.png differ diff --git a/1.2/reference/common_8h_source.html b/1.2/reference/common_8h_source.html new file mode 100644 index 000000000..4ed4b6803 --- /dev/null +++ b/1.2/reference/common_8h_source.html @@ -0,0 +1,474 @@ + + + + + + + + Crow: include/crow/common.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
common.h
+
+
+
1 #pragma once
+
2 
+
3 #include <vector>
+
4 #include <string>
+
5 #include <stdexcept>
+
6 #include <iostream>
+
7 #include "crow/utility.h"
+
8 
+
9 namespace crow
+
10 {
+
11  const char cr = '\r';
+
12  const char lf = '\n';
+
13  const std::string crlf("\r\n");
+
14 
+
15  enum class HTTPMethod : char
+
16  {
+
17 #ifndef DELETE
+
18  DELETE = 0,
+
19  GET,
+
20  HEAD,
+
21  POST,
+
22  PUT,
+
23 
+
24  CONNECT,
+
25  OPTIONS,
+
26  TRACE,
+
27 
+
28  PATCH,
+
29  PURGE,
+
30 
+
31  COPY,
+
32  LOCK,
+
33  MKCOL,
+
34  MOVE,
+
35  PROPFIND,
+
36  PROPPATCH,
+
37  SEARCH,
+
38  UNLOCK,
+
39  BIND,
+
40  REBIND,
+
41  UNBIND,
+
42  ACL,
+
43 
+
44  REPORT,
+
45  MKACTIVITY,
+
46  CHECKOUT,
+
47  MERGE,
+
48 
+
49  MSEARCH,
+
50  NOTIFY,
+
51  SUBSCRIBE,
+
52  UNSUBSCRIBE,
+
53 
+
54  MKCALENDAR,
+
55 
+
56  LINK,
+
57  UNLINK,
+
58 
+
59  SOURCE,
+
60 #endif
+
61 
+
62  Delete = 0,
+
63  Get,
+
64  Head,
+
65  Post,
+
66  Put,
+
67 
+
68  Connect,
+
69  Options,
+
70  Trace,
+
71 
+
72  Patch,
+
73  Purge,
+
74 
+
75  Copy,
+
76  Lock,
+
77  MkCol,
+
78  Move,
+
79  Propfind,
+
80  Proppatch,
+
81  Search,
+
82  Unlock,
+
83  Bind,
+
84  Rebind,
+
85  Unbind,
+
86  Acl,
+
87 
+
88  Report,
+
89  MkActivity,
+
90  Checkout,
+
91  Merge,
+
92 
+
93  MSearch,
+
94  Notify,
+
95  Subscribe,
+
96  Unsubscribe,
+
97 
+
98  MkCalendar,
+
99 
+
100  Link,
+
101  Unlink,
+
102 
+
103  Source,
+
104 
+
105 
+
106  InternalMethodCount,
+
107  // should not add an item below this line: used for array count
+
108  };
+
109 
+
110  constexpr const char* method_strings[] =
+
111  {
+
112  "DELETE",
+
113  "GET",
+
114  "HEAD",
+
115  "POST",
+
116  "PUT",
+
117 
+
118  "CONNECT",
+
119  "OPTIONS",
+
120  "TRACE",
+
121 
+
122  "PATCH",
+
123  "PURGE",
+
124 
+
125  "COPY",
+
126  "LOCK",
+
127  "MKCOL",
+
128  "MOVE",
+
129  "PROPFIND",
+
130  "PROPPATCH",
+
131  "SEARCH",
+
132  "UNLOCK",
+
133  "BIND",
+
134  "REBIND",
+
135  "UNBIND",
+
136  "ACL",
+
137 
+
138  "REPORT",
+
139  "MKACTIVITY",
+
140  "CHECKOUT",
+
141  "MERGE",
+
142 
+
143  "M-SEARCH",
+
144  "NOTIFY",
+
145  "SUBSCRIBE",
+
146  "UNSUBSCRIBE",
+
147 
+
148  "MKCALENDAR",
+
149 
+
150  "LINK",
+
151  "UNLINK",
+
152 
+
153  "SOURCE"};
+
154 
+
155 
+
156  inline std::string method_name(HTTPMethod method)
+
157  {
+
158  if (CROW_LIKELY(method < HTTPMethod::InternalMethodCount))
+
159  {
+
160  return method_strings[(unsigned char)method];
+
161  }
+
162  return "invalid";
+
163  }
+
164 
+
165  // clang-format off
+
166 
+
167  enum status
+
168  {
+
169  CONTINUE = 100,
+
170  SWITCHING_PROTOCOLS = 101,
+
171 
+
172  OK = 200,
+
173  CREATED = 201,
+
174  ACCEPTED = 202,
+
175  NON_AUTHORITATIVE_INFORMATION = 203,
+
176  NO_CONTENT = 204,
+
177  RESET_CONTENT = 205,
+
178  PARTIAL_CONTENT = 206,
+
179 
+
180  MULTIPLE_CHOICES = 300,
+
181  MOVED_PERMANENTLY = 301,
+
182  FOUND = 302,
+
183  SEE_OTHER = 303,
+
184  NOT_MODIFIED = 304,
+
185  TEMPORARY_REDIRECT = 307,
+
186  PERMANENT_REDIRECT = 308,
+
187 
+
188  BAD_REQUEST = 400,
+
189  UNAUTHORIZED = 401,
+
190  FORBIDDEN = 403,
+
191  NOT_FOUND = 404,
+
192  METHOD_NOT_ALLOWED = 405,
+
193  NOT_ACCEPTABLE = 406,
+
194  PROXY_AUTHENTICATION_REQUIRED = 407,
+
195  CONFLICT = 409,
+
196  GONE = 410,
+
197  PAYLOAD_TOO_LARGE = 413,
+
198  UNSUPPORTED_MEDIA_TYPE = 415,
+
199  RANGE_NOT_SATISFIABLE = 416,
+
200  EXPECTATION_FAILED = 417,
+
201  PRECONDITION_REQUIRED = 428,
+
202  TOO_MANY_REQUESTS = 429,
+
203  UNAVAILABLE_FOR_LEGAL_REASONS = 451,
+
204 
+
205  INTERNAL_SERVER_ERROR = 500,
+
206  NOT_IMPLEMENTED = 501,
+
207  BAD_GATEWAY = 502,
+
208  SERVICE_UNAVAILABLE = 503,
+
209  GATEWAY_TIMEOUT = 504,
+
210  VARIANT_ALSO_NEGOTIATES = 506
+
211  };
+
212 
+
213  // clang-format on
+
214 
+
215  enum class ParamType : char
+
216  {
+
217  INT,
+
218  UINT,
+
219  DOUBLE,
+
220  STRING,
+
221  PATH,
+
222 
+
223  MAX
+
224  };
+
225 
+
226  /// @cond SKIP
+
227  struct routing_params
+
228  {
+
229  std::vector<int64_t> int_params;
+
230  std::vector<uint64_t> uint_params;
+
231  std::vector<double> double_params;
+
232  std::vector<std::string> string_params;
+
233 
+
234  void debug_print() const
+
235  {
+
236  std::cerr << "routing_params" << std::endl;
+
237  for (auto i : int_params)
+
238  std::cerr << i << ", ";
+
239  std::cerr << std::endl;
+
240  for (auto i : uint_params)
+
241  std::cerr << i << ", ";
+
242  std::cerr << std::endl;
+
243  for (auto i : double_params)
+
244  std::cerr << i << ", ";
+
245  std::cerr << std::endl;
+
246  for (auto& i : string_params)
+
247  std::cerr << i << ", ";
+
248  std::cerr << std::endl;
+
249  }
+
250 
+
251  template<typename T>
+
252  T get(unsigned) const;
+
253  };
+
254 
+
255  template<>
+
256  inline int64_t routing_params::get<int64_t>(unsigned index) const
+
257  {
+
258  return int_params[index];
+
259  }
+
260 
+
261  template<>
+
262  inline uint64_t routing_params::get<uint64_t>(unsigned index) const
+
263  {
+
264  return uint_params[index];
+
265  }
+
266 
+
267  template<>
+
268  inline double routing_params::get<double>(unsigned index) const
+
269  {
+
270  return double_params[index];
+
271  }
+
272 
+
273  template<>
+
274  inline std::string routing_params::get<std::string>(unsigned index) const
+
275  {
+
276  return string_params[index];
+
277  }
+
278  /// @endcond
+
279 
+ +
281  {
+
282  uint16_t rule_index;
+
283  std::vector<uint16_t> blueprint_indices;
+
284  routing_params r_params;
+
285  HTTPMethod method;
+
286 
+ +
288 
+
289  routing_handle_result(uint16_t rule_index_, std::vector<uint16_t> blueprint_indices_, routing_params r_params_):
+
290  rule_index(rule_index_),
+
291  blueprint_indices(blueprint_indices_),
+
292  r_params(r_params_) {}
+
293 
+
294  routing_handle_result(uint16_t rule_index_, std::vector<uint16_t> blueprint_indices_, routing_params r_params_, HTTPMethod method_):
+
295  rule_index(rule_index_),
+
296  blueprint_indices(blueprint_indices_),
+
297  r_params(r_params_),
+
298  method(method_) {}
+
299  };
+
300 } // namespace crow
+
301 
+
302 // clang-format off
+
303 #ifndef CROW_MSVC_WORKAROUND
+
304 constexpr crow::HTTPMethod method_from_string(const char* str)
+
305 {
+
306  return crow::black_magic::is_equ_p(str, "GET", 3) ? crow::HTTPMethod::Get :
+
307  crow::black_magic::is_equ_p(str, "DELETE", 6) ? crow::HTTPMethod::Delete :
+
308  crow::black_magic::is_equ_p(str, "HEAD", 4) ? crow::HTTPMethod::Head :
+
309  crow::black_magic::is_equ_p(str, "POST", 4) ? crow::HTTPMethod::Post :
+
310  crow::black_magic::is_equ_p(str, "PUT", 3) ? crow::HTTPMethod::Put :
+
311 
+
312  crow::black_magic::is_equ_p(str, "OPTIONS", 7) ? crow::HTTPMethod::Options :
+
313  crow::black_magic::is_equ_p(str, "CONNECT", 7) ? crow::HTTPMethod::Connect :
+
314  crow::black_magic::is_equ_p(str, "TRACE", 5) ? crow::HTTPMethod::Trace :
+
315 
+
316  crow::black_magic::is_equ_p(str, "PATCH", 5) ? crow::HTTPMethod::Patch :
+
317  crow::black_magic::is_equ_p(str, "PURGE", 5) ? crow::HTTPMethod::Purge :
+
318  crow::black_magic::is_equ_p(str, "COPY", 4) ? crow::HTTPMethod::Copy :
+
319  crow::black_magic::is_equ_p(str, "LOCK", 4) ? crow::HTTPMethod::Lock :
+
320  crow::black_magic::is_equ_p(str, "MKCOL", 5) ? crow::HTTPMethod::MkCol :
+
321  crow::black_magic::is_equ_p(str, "MOVE", 4) ? crow::HTTPMethod::Move :
+
322  crow::black_magic::is_equ_p(str, "PROPFIND", 8) ? crow::HTTPMethod::Propfind :
+
323  crow::black_magic::is_equ_p(str, "PROPPATCH", 9) ? crow::HTTPMethod::Proppatch :
+
324  crow::black_magic::is_equ_p(str, "SEARCH", 6) ? crow::HTTPMethod::Search :
+
325  crow::black_magic::is_equ_p(str, "UNLOCK", 6) ? crow::HTTPMethod::Unlock :
+
326  crow::black_magic::is_equ_p(str, "BIND", 4) ? crow::HTTPMethod::Bind :
+
327  crow::black_magic::is_equ_p(str, "REBIND", 6) ? crow::HTTPMethod::Rebind :
+
328  crow::black_magic::is_equ_p(str, "UNBIND", 6) ? crow::HTTPMethod::Unbind :
+
329  crow::black_magic::is_equ_p(str, "ACL", 3) ? crow::HTTPMethod::Acl :
+
330 
+
331  crow::black_magic::is_equ_p(str, "REPORT", 6) ? crow::HTTPMethod::Report :
+
332  crow::black_magic::is_equ_p(str, "MKACTIVITY", 10) ? crow::HTTPMethod::MkActivity :
+
333  crow::black_magic::is_equ_p(str, "CHECKOUT", 8) ? crow::HTTPMethod::Checkout :
+
334  crow::black_magic::is_equ_p(str, "MERGE", 5) ? crow::HTTPMethod::Merge :
+
335 
+
336  crow::black_magic::is_equ_p(str, "MSEARCH", 7) ? crow::HTTPMethod::MSearch :
+
337  crow::black_magic::is_equ_p(str, "NOTIFY", 6) ? crow::HTTPMethod::Notify :
+
338  crow::black_magic::is_equ_p(str, "SUBSCRIBE", 9) ? crow::HTTPMethod::Subscribe :
+
339  crow::black_magic::is_equ_p(str, "UNSUBSCRIBE", 11) ? crow::HTTPMethod::Unsubscribe :
+
340 
+
341  crow::black_magic::is_equ_p(str, "MKCALENDAR", 10) ? crow::HTTPMethod::MkCalendar :
+
342 
+
343  crow::black_magic::is_equ_p(str, "LINK", 4) ? crow::HTTPMethod::Link :
+
344  crow::black_magic::is_equ_p(str, "UNLINK", 6) ? crow::HTTPMethod::Unlink :
+
345 
+
346  crow::black_magic::is_equ_p(str, "SOURCE", 6) ? crow::HTTPMethod::Source :
+
347  throw std::runtime_error("invalid http method");
+
348 }
+
349 
+
350 constexpr crow::HTTPMethod operator"" _method(const char* str, size_t /*len*/)
+
351 {
+
352  return method_from_string( str );
+
353 }
+
354 #endif
+
355 // clang-format on
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
Definition: common.h:281
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/compression_8h_source.html b/1.2/reference/compression_8h_source.html new file mode 100644 index 000000000..0b2662c25 --- /dev/null +++ b/1.2/reference/compression_8h_source.html @@ -0,0 +1,217 @@ + + + + + + + + Crow: include/crow/compression.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
compression.h
+
+
+
1 #ifdef CROW_ENABLE_COMPRESSION
+
2 #pragma once
+
3 
+
4 #include <string>
+
5 #include <zlib.h>
+
6 
+
7 // http://zlib.net/manual.html
+
8 namespace crow // NOTE: Already documented in "crow/app.h"
+
9 {
+
10  namespace compression
+
11  {
+
12  // Values used in the 'windowBits' parameter for deflateInit2.
+
13  enum algorithm
+
14  {
+
15  // 15 is the default value for deflate
+
16  DEFLATE = 15,
+
17  // windowBits can also be greater than 15 for optional gzip encoding.
+
18  // Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper.
+
19  GZIP = 15 | 16,
+
20  };
+
21 
+
22  inline std::string compress_string(std::string const& str, algorithm algo)
+
23  {
+
24  std::string compressed_str;
+
25  z_stream stream{};
+
26  // Initialize with the default values
+
27  if (::deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, algo, 8, Z_DEFAULT_STRATEGY) == Z_OK)
+
28  {
+
29  char buffer[8192];
+
30 
+
31  stream.avail_in = str.size();
+
32  // zlib does not take a const pointer. The data is not altered.
+
33  stream.next_in = const_cast<Bytef*>(reinterpret_cast<const Bytef*>(str.c_str()));
+
34 
+
35  int code = Z_OK;
+
36  do
+
37  {
+
38  stream.avail_out = sizeof(buffer);
+
39  stream.next_out = reinterpret_cast<Bytef*>(&buffer[0]);
+
40 
+
41  code = ::deflate(&stream, Z_FINISH);
+
42  // Successful and non-fatal error code returned by deflate when used with Z_FINISH flush
+
43  if (code == Z_OK || code == Z_STREAM_END)
+
44  {
+
45  std::copy(&buffer[0], &buffer[sizeof(buffer) - stream.avail_out], std::back_inserter(compressed_str));
+
46  }
+
47 
+
48  } while (code == Z_OK);
+
49 
+
50  if (code != Z_STREAM_END)
+
51  compressed_str.clear();
+
52 
+
53  ::deflateEnd(&stream);
+
54  }
+
55 
+
56  return compressed_str;
+
57  }
+
58 
+
59  inline std::string decompress_string(std::string const& deflated_string)
+
60  {
+
61  std::string inflated_string;
+
62  Bytef tmp[8192];
+
63 
+
64  z_stream zstream{};
+
65  zstream.avail_in = deflated_string.size();
+
66  // Nasty const_cast but zlib won't alter its contents
+
67  zstream.next_in = const_cast<Bytef*>(reinterpret_cast<Bytef const*>(deflated_string.c_str()));
+
68  // Initialize with automatic header detection, for gzip support
+
69  if (::inflateInit2(&zstream, MAX_WBITS | 32) == Z_OK)
+
70  {
+
71  do
+
72  {
+
73  zstream.avail_out = sizeof(tmp);
+
74  zstream.next_out = &tmp[0];
+
75 
+
76  auto ret = ::inflate(&zstream, Z_NO_FLUSH);
+
77  if (ret == Z_OK || ret == Z_STREAM_END)
+
78  {
+
79  std::copy(&tmp[0], &tmp[sizeof(tmp) - zstream.avail_out], std::back_inserter(inflated_string));
+
80  }
+
81  else
+
82  {
+
83  // Something went wrong with inflate; make sure we return an empty string
+
84  inflated_string.clear();
+
85  break;
+
86  }
+
87 
+
88  } while (zstream.avail_out == 0);
+
89 
+
90  // Free zlib's internal memory
+
91  ::inflateEnd(&zstream);
+
92  }
+
93 
+
94  return inflated_string;
+
95  }
+
96  } // namespace compression
+
97 } // namespace crow
+
98 
+
99 #endif
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/cookie__parser_8h_source.html b/1.2/reference/cookie__parser_8h_source.html new file mode 100644 index 000000000..d6e2ff13a --- /dev/null +++ b/1.2/reference/cookie__parser_8h_source.html @@ -0,0 +1,432 @@ + + + + + + + + Crow: include/crow/middlewares/cookie_parser.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
cookie_parser.h
+
+
+
1 #pragma once
+
2 #include <iomanip>
+
3 #include <memory>
+
4 #include "crow/utility.h"
+
5 #include "crow/http_request.h"
+
6 #include "crow/http_response.h"
+
7 
+
8 namespace crow
+
9 {
+
10  // Any middleware requires following 3 members:
+
11 
+
12  // struct context;
+
13  // storing data for the middleware; can be read from another middleware or handlers
+
14 
+
15  // before_handle
+
16  // called before handling the request.
+
17  // if res.end() is called, the operation is halted.
+
18  // (still call after_handle of this middleware)
+
19  // 2 signatures:
+
20  // void before_handle(request& req, response& res, context& ctx)
+
21  // if you only need to access this middlewares context.
+
22  // template <typename AllContext>
+
23  // void before_handle(request& req, response& res, context& ctx, AllContext& all_ctx)
+
24  // you can access another middlewares' context by calling `all_ctx.template get<MW>()'
+
25  // ctx == all_ctx.template get<CurrentMiddleware>()
+
26 
+
27  // after_handle
+
28  // called after handling the request.
+
29  // void after_handle(request& req, response& res, context& ctx)
+
30  // template <typename AllContext>
+
31  // void after_handle(request& req, response& res, context& ctx, AllContext& all_ctx)
+
32 
+
33  struct CookieParser
+
34  {
+
35  // Cookie stores key, value and attributes
+
36  struct Cookie
+
37  {
+
38  enum class SameSitePolicy
+
39  {
+
40  Strict,
+
41  Lax,
+
42  None
+
43  };
+
44 
+
45  template<typename U>
+
46  Cookie(const std::string& key, U&& value):
+
47  Cookie()
+
48  {
+
49  key_ = key;
+
50  value_ = std::forward<U>(value);
+
51  }
+
52 
+
53  Cookie(const std::string& key):
+
54  Cookie(key, "") {}
+
55 
+
56  // format cookie to HTTP header format
+
57  std::string dump() const
+
58  {
+
59  const static char* HTTP_DATE_FORMAT = "%a, %d %b %Y %H:%M:%S GMT";
+
60 
+
61  std::stringstream ss;
+
62  ss << key_ << '=';
+
63  ss << (value_.empty() ? "\"\"" : value_);
+
64  dumpString(ss, !domain_.empty(), "Domain=", domain_);
+
65  dumpString(ss, !path_.empty(), "Path=", path_);
+
66  dumpString(ss, secure_, "Secure");
+
67  dumpString(ss, httponly_, "HttpOnly");
+
68  if (expires_at_)
+
69  {
+
70  ss << DIVIDER << "Expires="
+
71  << std::put_time(expires_at_.get(), HTTP_DATE_FORMAT);
+
72  }
+
73  if (max_age_)
+
74  {
+
75  ss << DIVIDER << "Max-Age=" << *max_age_;
+
76  }
+
77  if (same_site_)
+
78  {
+
79  ss << DIVIDER << "SameSite=";
+
80  switch (*same_site_)
+
81  {
+
82  case SameSitePolicy::Strict:
+
83  ss << "Strict";
+
84  break;
+
85  case SameSitePolicy::Lax:
+
86  ss << "Lax";
+
87  break;
+
88  case SameSitePolicy::None:
+
89  ss << "None";
+
90  break;
+
91  }
+
92  }
+
93  return ss.str();
+
94  }
+
95 
+
96  const std::string& name()
+
97  {
+
98  return key_;
+
99  }
+
100 
+
101  template<typename U>
+
102  Cookie& value(U&& value)
+
103  {
+
104  value_ = std::forward<U>(value);
+
105  return *this;
+
106  }
+
107 
+
108  // Expires attribute
+
109  Cookie& expires(const std::tm& time)
+
110  {
+
111  expires_at_ = std::unique_ptr<std::tm>(new std::tm(time));
+
112  return *this;
+
113  }
+
114 
+
115  // Max-Age attribute
+
116  Cookie& max_age(long long seconds)
+
117  {
+
118  max_age_ = std::unique_ptr<long long>(new long long(seconds));
+
119  return *this;
+
120  }
+
121 
+
122  // Domain attribute
+
123  Cookie& domain(const std::string& name)
+
124  {
+
125  domain_ = name;
+
126  return *this;
+
127  }
+
128 
+
129  // Path attribute
+
130  Cookie& path(const std::string& path)
+
131  {
+
132  path_ = path;
+
133  return *this;
+
134  }
+
135 
+
136  // Secured attribute
+
137  Cookie& secure()
+
138  {
+
139  secure_ = true;
+
140  return *this;
+
141  }
+
142 
+
143  // HttpOnly attribute
+
144  Cookie& httponly()
+
145  {
+
146  httponly_ = true;
+
147  return *this;
+
148  }
+
149 
+
150  // SameSite attribute
+
151  Cookie& same_site(SameSitePolicy ssp)
+
152  {
+
153  same_site_ = std::unique_ptr<SameSitePolicy>(new SameSitePolicy(ssp));
+
154  return *this;
+
155  }
+
156 
+
157  Cookie(const Cookie& c):
+
158  key_(c.key_),
+
159  value_(c.value_),
+
160  domain_(c.domain_),
+
161  path_(c.path_),
+
162  secure_(c.secure_),
+
163  httponly_(c.httponly_)
+
164  {
+
165  if (c.max_age_)
+
166  max_age_ = std::unique_ptr<long long>(new long long(*c.max_age_));
+
167 
+
168  if (c.expires_at_)
+
169  expires_at_ = std::unique_ptr<std::tm>(new std::tm(*c.expires_at_));
+
170 
+
171  if (c.same_site_)
+
172  same_site_ = std::unique_ptr<SameSitePolicy>(new SameSitePolicy(*c.same_site_));
+
173  }
+
174 
+
175  private:
+
176  Cookie() = default;
+
177 
+
178  static void dumpString(std::stringstream& ss, bool cond, const char* prefix,
+
179  const std::string& value = "")
+
180  {
+
181  if (cond)
+
182  {
+
183  ss << DIVIDER << prefix << value;
+
184  }
+
185  }
+
186 
+
187  private:
+
188  std::string key_;
+
189  std::string value_;
+
190  std::unique_ptr<long long> max_age_{};
+
191  std::string domain_ = "";
+
192  std::string path_ = "";
+
193  bool secure_ = false;
+
194  bool httponly_ = false;
+
195  std::unique_ptr<std::tm> expires_at_{};
+
196  std::unique_ptr<SameSitePolicy> same_site_{};
+
197 
+
198  static constexpr const char* DIVIDER = "; ";
+
199  };
+
200 
+
201 
+
202  struct context
+
203  {
+
204  std::unordered_map<std::string, std::string> jar;
+
205 
+
206  std::string get_cookie(const std::string& key) const
+
207  {
+
208  auto cookie = jar.find(key);
+
209  if (cookie != jar.end())
+
210  return cookie->second;
+
211  return {};
+
212  }
+
213 
+
214  template<typename U>
+
215  Cookie& set_cookie(const std::string& key, U&& value)
+
216  {
+
217  cookies_to_add.emplace_back(key, std::forward<U>(value));
+
218  return cookies_to_add.back();
+
219  }
+
220 
+
221  Cookie& set_cookie(Cookie cookie)
+
222  {
+
223  cookies_to_add.push_back(std::move(cookie));
+
224  return cookies_to_add.back();
+
225  }
+
226 
+
227  private:
+
228  friend struct CookieParser;
+
229  std::vector<Cookie> cookies_to_add;
+
230  };
+
231 
+
232  void before_handle(request& req, response& res, context& ctx)
+
233  {
+
234  // TODO(dranikpg): remove copies, use string_view with c++17
+
235  int count = req.headers.count("Cookie");
+
236  if (!count)
+
237  return;
+
238  if (count > 1)
+
239  {
+
240  res.code = 400;
+
241  res.end();
+
242  return;
+
243  }
+
244  std::string cookies = req.get_header_value("Cookie");
+
245  size_t pos = 0;
+
246  while (pos < cookies.size())
+
247  {
+
248  size_t pos_equal = cookies.find('=', pos);
+
249  if (pos_equal == cookies.npos)
+
250  break;
+
251  std::string name = cookies.substr(pos, pos_equal - pos);
+
252  name = utility::trim(name);
+
253  pos = pos_equal + 1;
+
254  if (pos == cookies.size())
+
255  break;
+
256 
+
257  size_t pos_semicolon = cookies.find(';', pos);
+
258  std::string value = cookies.substr(pos, pos_semicolon - pos);
+
259 
+
260  value = utility::trim(value);
+
261  if (value[0] == '"' && value[value.size() - 1] == '"')
+
262  {
+
263  value = value.substr(1, value.size() - 2);
+
264  }
+
265 
+
266  ctx.jar.emplace(std::move(name), std::move(value));
+
267 
+
268  pos = pos_semicolon;
+
269  if (pos == cookies.npos)
+
270  break;
+
271  pos++;
+
272  }
+
273  }
+
274 
+
275  void after_handle(request& /*req*/, response& res, context& ctx)
+
276  {
+
277  for (const auto& cookie : ctx.cookies_to_add)
+
278  {
+
279  res.add_header("Set-Cookie", cookie.dump());
+
280  }
+
281  }
+
282  };
+
283 
+
284  /*
+
285  App<CookieParser, AnotherJarMW> app;
+
286  A B C
+
287  A::context
+
288  int aa;
+
289 
+
290  ctx1 : public A::context
+
291  ctx2 : public ctx1, public B::context
+
292  ctx3 : public ctx2, public C::context
+
293 
+
294  C depends on A
+
295 
+
296  C::handle
+
297  context.aaa
+
298 
+
299  App::context : private CookieParser::context, ...
+
300  {
+
301  jar
+
302 
+
303  }
+
304 
+
305  SimpleApp
+
306  */
+
307 } // namespace crow
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+ + + +
An HTTP request.
Definition: http_request.h:36
+
HTTP response.
Definition: http_response.h:34
+
int code
The Status code for the response.
Definition: http_response.h:40
+
void end()
Set the response completion flag and call the handler (to send the response).
Definition: http_response.h:237
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/cors_8h_source.html b/1.2/reference/cors_8h_source.html new file mode 100644 index 000000000..f233e0dcc --- /dev/null +++ b/1.2/reference/cors_8h_source.html @@ -0,0 +1,342 @@ + + + + + + + + Crow: include/crow/middlewares/cors.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
cors.h
+
+
+
1 #pragma once
+
2 #include "crow/http_request.h"
+
3 #include "crow/http_response.h"
+
4 #include "crow/routing.h"
+
5 
+
6 namespace crow
+
7 {
+
8  struct CORSHandler;
+
9 
+
10  /// Used for tuning CORS policies
+
11  struct CORSRules
+
12  {
+
13  friend struct crow::CORSHandler;
+
14 
+
15  /// Set Access-Control-Allow-Origin. Default is "*"
+
16  CORSRules& origin(const std::string& origin)
+
17  {
+
18  origin_ = origin;
+
19  return *this;
+
20  }
+
21 
+
22  /// Set Access-Control-Allow-Methods. Default is "*"
+
23  CORSRules& methods(crow::HTTPMethod method)
+
24  {
+
25  add_list_item(methods_, crow::method_name(method));
+
26  return *this;
+
27  }
+
28 
+
29  /// Set Access-Control-Allow-Methods. Default is "*"
+
30  template<typename... Methods>
+
31  CORSRules& methods(crow::HTTPMethod method, Methods... method_list)
+
32  {
+
33  add_list_item(methods_, crow::method_name(method));
+
34  methods(method_list...);
+
35  return *this;
+
36  }
+
37 
+
38  /// Set Access-Control-Allow-Headers. Default is "*"
+
39  CORSRules& headers(const std::string& header)
+
40  {
+
41  add_list_item(headers_, header);
+
42  return *this;
+
43  }
+
44 
+
45  /// Set Access-Control-Allow-Headers. Default is "*"
+
46  template<typename... Headers>
+
47  CORSRules& headers(const std::string& header, Headers... header_list)
+
48  {
+
49  add_list_item(headers_, header);
+
50  headers(header_list...);
+
51  return *this;
+
52  }
+
53 
+
54  /// Set Access-Control-Max-Age. Default is none
+ +
56  {
+
57  max_age_ = std::to_string(max_age);
+
58  return *this;
+
59  }
+
60 
+
61  /// Enable Access-Control-Allow-Credentials
+ +
63  {
+
64  allow_credentials_ = true;
+
65  return *this;
+
66  }
+
67 
+
68  /// Ignore CORS and don't send any headers
+
69  void ignore()
+
70  {
+
71  ignore_ = true;
+
72  }
+
73 
+
74  /// Handle CORS on specific prefix path
+
75  CORSRules& prefix(const std::string& prefix);
+
76 
+
77  /// Handle CORS for specific blueprint
+
78  CORSRules& blueprint(const Blueprint& bp);
+
79 
+
80  /// Global CORS policy
+
81  CORSRules& global();
+
82 
+
83  private:
+
84  CORSRules() = delete;
+
85  CORSRules(CORSHandler* handler):
+
86  handler_(handler) {}
+
87 
+
88  /// build comma separated list
+
89  void add_list_item(std::string& list, const std::string& val)
+
90  {
+
91  if (list == "*") list = "";
+
92  if (list.size() > 0) list += ", ";
+
93  list += val;
+
94  }
+
95 
+
96  /// Set header `key` to `value` if it is not set
+
97  void set_header_no_override(const std::string& key, const std::string& value, crow::response& res)
+
98  {
+
99  if (value.size() == 0) return;
+
100  if (!get_header_value(res.headers, key).empty()) return;
+
101  res.add_header(key, value);
+
102  }
+
103 
+
104  /// Set response headers
+
105  void apply(crow::response& res)
+
106  {
+
107  if (ignore_) return;
+
108  set_header_no_override("Access-Control-Allow-Origin", origin_, res);
+
109  set_header_no_override("Access-Control-Allow-Methods", methods_, res);
+
110  set_header_no_override("Access-Control-Allow-Headers", headers_, res);
+
111  set_header_no_override("Access-Control-Max-Age", max_age_, res);
+
112  if (allow_credentials_) set_header_no_override("Access-Control-Allow-Credentials", "true", res);
+
113  }
+
114 
+
115  bool ignore_ = false;
+
116  // TODO: support multiple origins that are dynamically selected
+
117  std::string origin_ = "*";
+
118  std::string methods_ = "*";
+
119  std::string headers_ = "*";
+
120  std::string max_age_;
+
121  bool allow_credentials_ = false;
+
122 
+
123  CORSHandler* handler_;
+
124  };
+
125 
+
126  /// CORSHandler is a global middleware for setting CORS headers.
+
127 
+
128  ///
+
129  /// By default, it sets Access-Control-Allow-Origin/Methods/Headers to "*".
+
130  /// The default behaviour can be changed with the `global()` cors rule.
+
131  /// Additional rules for prexies can be added with `prefix()`.
+
132  struct CORSHandler
+
133  {
+
134  struct context
+
135  {};
+
136 
+
137  void before_handle(crow::request& /*req*/, crow::response& /*res*/, context& /*ctx*/)
+
138  {}
+
139 
+
140  void after_handle(crow::request& req, crow::response& res, context& /*ctx*/)
+
141  {
+
142  auto& rule = find_rule(req.url);
+
143  rule.apply(res);
+
144  }
+
145 
+
146  /// Handle CORS on a specific prefix path
+
147  CORSRules& prefix(const std::string& prefix)
+
148  {
+
149  rules.emplace_back(prefix, CORSRules(this));
+
150  return rules.back().second;
+
151  }
+
152 
+
153  /// Handle CORS for a specific blueprint
+ +
155  {
+
156  rules.emplace_back(bp.prefix(), CORSRules(this));
+
157  return rules.back().second;
+
158  }
+
159 
+
160  /// Get the global CORS policy
+ +
162  {
+
163  return default_;
+
164  }
+
165 
+
166  private:
+
167  CORSRules& find_rule(const std::string& path)
+
168  {
+
169  // TODO: use a trie in case of many rules
+
170  for (auto& rule : rules)
+
171  {
+
172  // Check if path starts with a rules prefix
+
173  if (path.rfind(rule.first, 0) == 0)
+
174  {
+
175  return rule.second;
+
176  }
+
177  }
+
178  return default_;
+
179  }
+
180 
+
181  std::vector<std::pair<std::string, CORSRules>> rules;
+
182  CORSRules default_ = CORSRules(this);
+
183  };
+
184 
+
185  inline CORSRules& CORSRules::prefix(const std::string& prefix)
+
186  {
+
187  return handler_->prefix(prefix);
+
188  }
+
189 
+ +
191  {
+
192  return handler_->blueprint(bp);
+
193  }
+
194 
+ +
196  {
+
197  return handler_->global();
+
198  }
+
199 
+
200 } // namespace crow
+
A blueprint can be considered a smaller section of a Crow app, specifically where the router is conec...
Definition: routing.h:1104
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
const std::string & get_header_value(const T &headers, const std::string &key)
Find and return the value associated with the key. (returns an empty string if nothing is found)
Definition: http_request.h:24
+
Definition: cors.h:135
+
CORSHandler is a global middleware for setting CORS headers.
Definition: cors.h:133
+
CORSRules & blueprint(const Blueprint &bp)
Handle CORS for a specific blueprint.
Definition: cors.h:154
+
CORSRules & prefix(const std::string &prefix)
Handle CORS on a specific prefix path.
Definition: cors.h:147
+
CORSRules & global()
Get the global CORS policy.
Definition: cors.h:161
+
Used for tuning CORS policies.
Definition: cors.h:12
+
CORSRules & global()
Global CORS policy.
Definition: cors.h:195
+
CORSRules & origin(const std::string &origin)
Set Access-Control-Allow-Origin. Default is "*".
Definition: cors.h:16
+
CORSRules & methods(crow::HTTPMethod method)
Set Access-Control-Allow-Methods. Default is "*".
Definition: cors.h:23
+
CORSRules & methods(crow::HTTPMethod method, Methods... method_list)
Set Access-Control-Allow-Methods. Default is "*".
Definition: cors.h:31
+
CORSRules & prefix(const std::string &prefix)
Handle CORS on specific prefix path.
Definition: cors.h:185
+
CORSRules & max_age(int max_age)
Set Access-Control-Max-Age. Default is none.
Definition: cors.h:55
+
CORSRules & allow_credentials()
Enable Access-Control-Allow-Credentials.
Definition: cors.h:62
+
CORSRules & blueprint(const Blueprint &bp)
Handle CORS for specific blueprint.
Definition: cors.h:190
+
CORSRules & headers(const std::string &header, Headers... header_list)
Set Access-Control-Allow-Headers. Default is "*".
Definition: cors.h:47
+
CORSRules & headers(const std::string &header)
Set Access-Control-Allow-Headers. Default is "*".
Definition: cors.h:39
+
void ignore()
Ignore CORS and don't send any headers.
Definition: cors.h:69
+
An HTTP request.
Definition: http_request.h:36
+
std::string url
The endpoint without any parameters.
Definition: http_request.h:39
+
HTTP response.
Definition: http_response.h:34
+
void add_header(std::string key, std::string value)
Add a new header to the response.
Definition: http_response.h:58
+
ci_map headers
HTTP headers.
Definition: http_response.h:42
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/crow_8h_source.html b/1.2/reference/crow_8h_source.html new file mode 100644 index 000000000..1944120c1 --- /dev/null +++ b/1.2/reference/crow_8h_source.html @@ -0,0 +1,144 @@ + + + + + + + + Crow: include/crow.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow.h
+
+
+
1 #pragma once
+
2 #include "crow/query_string.h"
+
3 #include "crow/http_parser_merged.h"
+
4 #include "crow/ci_map.h"
+
5 #include "crow/TinySHA1.hpp"
+
6 #include "crow/settings.h"
+
7 #include "crow/socket_adaptors.h"
+
8 #include "crow/json.h"
+
9 #include "crow/mustache.h"
+
10 #include "crow/logging.h"
+
11 #include "crow/task_timer.h"
+
12 #include "crow/utility.h"
+
13 #include "crow/common.h"
+
14 #include "crow/http_request.h"
+
15 #include "crow/websocket.h"
+
16 #include "crow/parser.h"
+
17 #include "crow/http_response.h"
+
18 #include "crow/multipart.h"
+
19 #include "crow/routing.h"
+
20 #include "crow/middleware.h"
+
21 #include "crow/middleware_context.h"
+
22 #include "crow/compression.h"
+
23 #include "crow/http_connection.h"
+
24 #include "crow/http_server.h"
+
25 #include "crow/app.h"
+
TinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based on the implementation in ...
+
This file includes the definition of the crow::Crow class, the crow::App and crow::SimpleApp aliases,...
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/custom.css b/1.2/reference/custom.css new file mode 100644 index 000000000..ac39ccba9 --- /dev/null +++ b/1.2/reference/custom.css @@ -0,0 +1,338 @@ +div.fragment, pre.fragment { + margin: 0; + padding: 4px; +} + +/*********************************************/ +/** Main content **/ +/*********************************************/ +.contents { + margin: 10px auto !important; + padding: 0 10px; + max-width: 1200px; +} + +/*********************************************/ +/** Inline code **/ +/*********************************************/ +p code, +li code, +td code, +dd code { + display: inline; + padding: 0px 6px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + + background-color: #CCCCCC; + border: 1px solid #333333; + + color: #333333; +} + +/*********************************************/ +/** Table of Contents (ToC) **/ +/*********************************************/ +div.toc { + margin: 0 !important; + border-radius: 4px !important; +} + +div.toc h3 { + font-size: 150%; + color: inherit; +} + +/*********************************************/ +/** Content table **/ +/*********************************************/ +.contents table.doxtable { + margin: 0 auto; +} + +/*********************************************/ +/** Field table **/ +/*********************************************/ +.fieldtable { + box-shadow: none !important; + -webkit-box-shadow: none; + -moz-box-shadow: none; +} + +/*********************************************/ +/** Memitem and memtitle **/ +/*********************************************/ +.memitem, +.memproto, +.memdoc { + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + background-image: none; +} + +/*********************************************/ +/** TOP navigation **/ +/*********************************************/ +.tablist a:hover, +.tablist li.current a { + text-shadow: none; + -moz-text-shadow: none; + -webkit-text-shadow: none; +} + +/*********************************************/ +/** H1 in textblocks **/ +/*********************************************/ +.textblock h1 { + border-bottom: 1px solid #32363d; + border-left: 3px solid #32363d; + margin: 40px 0px 10px 0px; + padding-bottom: 10px; + padding-top: 10px; + padding-left: 5px; +} + +.textblock h1:first-child { + margin-top: 10px; +} + +/*********************************************/ +/** Note, warning **/ +/*********************************************/ +dl.note, +dl.warning, +dl.todo, +dl.deprecated, +dl.reflist { + border: 0; + padding: 0px; + margin: 4px 0px 4px 0px; + border-radius: 4px; +} + +dl.note dt, +dl.warning dt, +dl.todo dt, +dl.deprecated dt, +dl.reflist dt { + margin: 0; + font-size: 14px; + padding: 2px 4px; + + border: none; + border-top-left-radius: 0px; + border-top-right-radius:0px; + + font-weight: bold; + text-transform: uppercase; + color: #FFFFFF !important; + + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + text-shadow: none; +} + +dl.note dd, +dl.warning dd, +dl.todo dd, +dl.deprecated dd, +dl.reflist dd { + margin: 0; + padding: 4px; + background: none; + + color: #222222; + + border: 1px solid; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + border-top: none; + + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + text-shadow: none; +} + +dl.reflist dd { + margin-bottom: 15px; +} + +/* Background colors */ +dl.note {} +dl.warning {} +dl.todo {} +dl.deprecated {} +dl.reflist {} + +/* Header */ +dl.note dt { + background-color: #cbc693; +} + +dl.warning dt { + background-color: #bf5f82; +} + +dl.todo dt { + background-color: #82b3c9; +} + +dl.deprecated dt { + background-color: #af8eb5; +} + +dl.reflist dt { + background-color: #cbae82; +} + +/* Content */ +dl.note dd { + background-color: #fff9c4; + border-color: #cbc693; +} + +dl.warning dd { + background-color: #f48fb1; + border-color: #bf5f82; +} + +dl.todo dd { + background-color: #b3e5fc; + border-color: #82b3c9; +} + +dl.deprecated dd { + background-color: #e1bee7; + border-color: #af8eb5; +} + +dl.reflist dd { + background-color: #ffe0b2; + border-color: #cbae82; +} + +/*********************************************/ +/** Reference list **/ +/**Similar to warning/note/todo/... messages**/ +/*********************************************/ +dl.reflist { + +} + +/*********************************************/ +/** Note, warning **/ +/*********************************************/ +#docs_list { + padding: 0 10px; +} + +#docs_list ul { + margin: 0; + padding: 0; + list-style: none; +} + +#docs_list ul li { + display: inline-block; + border-right: 1px solid #BFBFBF; +} + +#docs_list ul li:last-child { + border-right: none; +} + +#docs_list ul li a { + display: block; + padding: 8px 13px; + font-weight: bold; + font-size: 15px; +} + +#docs_list ul li a:hover, +#docs_list ul li a.docs_current { + text-decoration: underline; +} + +/*********************************************/ +/** Resizable UI **/ +/*********************************************/ +.ui-resizable-e { + width: 3px; +} + +/*********************************************/ +/** Download url **/ +/*********************************************/ +.download_url { + font-weight: bold; + font-size: 150%; + line-height: 150%; +} + +/*********************************************/ +/** Syntax folor **/ +/*********************************************/ +div.line a { + text-decoration: underline; +} + +span.lineno a { + text-decoration: none; +} + +/*********************************************/ +/** Modules/Directory table **/ +/*********************************************/ +.directory .arrow { + height: initial; +} + +.directory td.entry { + padding: 3px 6px; +} + +/*********************************************/ +/** Mem items **/ +/*********************************************/ +.memproto table td { + font-family: monospace, fixed !important; +} + +td.memItemLeft, td.memItemRight { + font-family: monospace, fixed; +} + +.paramname, .paramname em { + font-style: italic; +} + +.memdoc { + text-shadow: none; +} + +.memItem { + font-family: monospace, fixed; +} + +.memItem table { + font-family: inherit; +} + +/*********************************************/ +/** Footer **/ +/*********************************************/ +img.footer { + height: 22px; +} + +/*********************************************/ +/** Custom scrollbar **/ +/*********************************************/ + +/*********************************************/ +/** Custom scrollbar **/ +/*********************************************/ diff --git a/1.2/reference/custom_dark_theme.css b/1.2/reference/custom_dark_theme.css new file mode 100644 index 000000000..cc7d8cabf --- /dev/null +++ b/1.2/reference/custom_dark_theme.css @@ -0,0 +1,481 @@ +/* Light background: #3 5 3 6 2 9; */ +/* New light dark background #3 2 3 6 3 d */ +/* Dark background: #d f e 5 f 2; */ + +/* TOP MENU */ +.sm-dox { + background: #dfe5f2 !important; +} + +.sm-dox a { + background: none; +} + +body { + background: #282828; + background-image: none; + color: #D8D8D8; + scrollbar-color: #303030 #141414; +} + +div.fragment, pre.fragment { + border: 1px solid #ffffff19; + background: #32363d; +} + +a, a:link, a:visited { + color: #859ed5 !important; +} + +.arrow { + color: #859ed5 +} + +.highlighted { + background: none !important; +} + +a.highlighted { + background: none !important; +} + +/*********************************************/ +/** Top main menu **/ +/*********************************************/ +#main-nav { + /* display: none; */ + border-bottom: 1px solid #32363d; +} + +#main-nav .sm-dox { + background: transparent !important; +} + +.sm-dox a { + text-shadow: none !important; + background: transparent !important; +} + +.sm-dox a:hover { + background: #282923 !important; +} + +.sm-dox { + text-shadow: none !important; + box-shadow: none !important; +} + +.sm-dox ul { + border: 1px solid #ffffff19; + background: #32363d; +} + +.directory tr.even { + background: #32363d; +} + + +/*********************************************/ +/** Top search **/ +/*********************************************/ +#MSearchSelectWindow { + border: 1px solid #ffffff19; + background: #32363d; +} + +a.selectItem { + padding: 3px; +} + +a.SelectItem:hover { + background: #282923 !important; +} + +#MSearchResultsWindow { + border: 1px solid #ffffff19; + background: #32363d; + color: #859ed5 !important; + border-radius: 5px; +} + +/*********************************************/ +/** Main menu **/ +/*********************************************/ +#nav-tree { + background: transparent; +} + +#nav-tree .selected { + background-image: none; + background: #32363d; +} + +/*********************************************/ +/** Main content **/ +/*********************************************/ + +/*********************************************/ +/** Inline code **/ +/*********************************************/ +p code, +li code, +td code, +dd code { + background-color: #14141480; + border: 1px solid #ffffff19; + color: #b9b9b9; +} + +/*********************************************/ +/** Table of Contents (ToC) **/ +/*********************************************/ +div.toc { + background: #32363d; + border: 1px solid #ffffff19; +} + +div.toc h3 { + font-size: 150%; + color: inherit; +} + +/*********************************************/ +/** Content table **/ +/*********************************************/ +table.doxtable tr:nth-child(even) td { + background: #32363d; +} + +div.header { + background: transparent; + border-bottom: 1px solid #32363d; +} + +/*********************************************/ +/** Field table **/ +/*********************************************/ +.fieldtable th { + background: #282923; + color: inherit; +} + +/*********************************************/ +/** Memitem and memtitle **/ +/*********************************************/ +.memdoc { + border: 1px solid #A8B8D9; +} + +/*********************************************/ +/** TOP navigation **/ +/*********************************************/ +.tabs, .tabs2, .tabs3 { + background: #DDDDDD; +} + +.tablist li { + background: transparent !important; +} + +.tablist a { + background-image: none; + border-right: 1px solid #999999; + + color: #32363d; +} + +.tablist a:hover, +.tablist li.current a { + text-decoration: none; + color: #101010; + background: #CCCCCC; + background-image: none; +} + +/*********************************************/ +/** H1 in textblocks **/ +/*********************************************/ + +/*********************************************/ +/** Note, warning **/ +/*********************************************/ + +/*********************************************/ +/** Reference list **/ +/**Similar to warning/note/todo/... messages**/ +/*********************************************/ +dl.reflist { + +} + + +/*********************************************/ +/** Note, warning **/ +/*********************************************/ +#docs_list { + background: #32363d; +} + +#docs_list ul li { + border-right: 1px solid #BFBFBF; +} + +#docs_list ul li a { + color: #1b1e21; +} + +#docs_list ul li a:hover, +#docs_list ul li a.docs_current { + background: #282923; +} + +/*********************************************/ +/** Resizable UI **/ +/*********************************************/ +.ui-resizable-e { + background: #32363d; +} + +/*********************************************/ +/** Download url **/ +/*********************************************/ + +/*********************************************/ +/** Syntax folor **/ +/*********************************************/ +div.line { + background: transparent; + color: #d7d7d7; +} + +div.line a { + color: inherit; +} + +span.keyword { + color: #f92472; + font-style: italic; +} + +span.keywordtype { + color: #67cfc1; + font-style: italic; +} + +span.keywordflow { + color: #f92472; + font-style: italic; +} + +span.comment { + color: #74705a; +} + +span.preprocessor { + color: #a6e22b; +} + +span.stringliteral { + color: #e7db74; +} + +span.charliteral { + color: #e7db74; +} + +span.vhdldigit { + color: #ff00ff; +} + +span.vhdlchar { + color: #000000; +} + +span.vhdlkeyword { + color: #700070; +} + +span.vhdllogic { + color: #ff0000; +} + +span.lineno { + background: transparent; +} + +span.lineno a { + background: transparent; +} + +/*********************************************/ +/** Modules/Directory table **/ +/*********************************************/ +.mdescLeft, .mdescRight, .memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background: #32363d; + color: inherit; +} + +.memtemplate { + color: #B4CCF9; +} + +.memSeparator { + border: none; + background: transparent; +} + +h2.groupheader { + color: #859ed5; +} + +/*********************************************/ +/** Mem items **/ +/*********************************************/ +.memtitle { + background: #32363d !important; + border-color: #ffffff19; +} + +.memitem { + background: #32363d !important; + color: inherit; + text-shadow: none; +} + +.memproto { + background: inherit; + border-color: #ffffff19; + color: inherit; + text-shadow: none; +} + +.memproto table td { + font-family: monospace, fixed !important; +} + +td.memItemLeft, td.memItemRight { + font-family: monospace, fixed; +} + +.paramname, .paramname em { + color: #bf5f82; +} + +.memdoc { + background: inherit; + border-color: #ffffff19; +} + + +/*********************************************/ +/** Footer **/ +/*********************************************/ +.titlearea { + border-bottom: 1px solid #32363d; +} + +/*********************************************/ +/** Footer **/ +/*********************************************/ +#nav-path { + background: transparent; +} + +#nav-path ul { + background: transparent; + color: inherit; + border: none; + border-top: 1px solid #32363d; +} + +.navpath li.footer { + color: inherit; +} + +.navpath li.navelem a { + text-shadow: none; +} + +/*********************************************/ +/** Custom scrollbar **/ +/*********************************************/ +::-webkit-scrollbar { + width: 10px; +} + +/* Track */ +::-webkit-scrollbar-track { + border-radius: 10px; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: #234567; + border: none; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: #32363d; +} + +/*********************************************/ +/** Custom scrollbar **/ +/*********************************************/ +h1.glow, h2.glow, h3.glow, +h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px #859ed5; +} + +#nav-tree .item { + margin: 5px; +} + +#MSearchBox .left{ + background: none; +} + +#MSearchBox .right{ + background: none; +} + +#MSearchField { + background: none; + border-bottom: solid 1px; + color: #bbb +} + +.MSearchBoxActive #MSearchField { + Color: #fff +} + +.SRSymbol { + color: #B4CCF9; +} + +a.SRScope { + color: #B4CCF9; +} + +.icon { + font-family: Arial, Helvetica; + font-weight: bold; + font-size: 12px; + height: 16px; + width: 16px; + display: inline-block; + background-color: #141414; + color: white; + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; + padding-top: 2px; + padding-left: 1px; + padding-right: 1px; +} + +#projectlogo { + vertical-align: inherit; +} diff --git a/1.2/reference/dir_5bc98d550c303c0206de23cf2f7c59bb.html b/1.2/reference/dir_5bc98d550c303c0206de23cf2f7c59bb.html new file mode 100644 index 000000000..ecce7530d --- /dev/null +++ b/1.2/reference/dir_5bc98d550c303c0206de23cf2f7c59bb.html @@ -0,0 +1,117 @@ + + + + + + + + Crow: include/crow/middlewares Directory Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
middlewares Directory Reference
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/dir_5bc98d550c303c0206de23cf2f7c59bb.js b/1.2/reference/dir_5bc98d550c303c0206de23cf2f7c59bb.js new file mode 100644 index 000000000..827b060f2 --- /dev/null +++ b/1.2/reference/dir_5bc98d550c303c0206de23cf2f7c59bb.js @@ -0,0 +1,7 @@ +var dir_5bc98d550c303c0206de23cf2f7c59bb = +[ + [ "cookie_parser.h", "cookie__parser_8h_source.html", null ], + [ "cors.h", "cors_8h_source.html", null ], + [ "session.h", "session_8h_source.html", null ], + [ "utf-8.h", "utf-8_8h_source.html", null ] +]; \ No newline at end of file diff --git a/1.2/reference/dir_d22c1cb87b72f01e1a7f207eb3bfd1ca.html b/1.2/reference/dir_d22c1cb87b72f01e1a7f207eb3bfd1ca.html new file mode 100644 index 000000000..df3d237ab --- /dev/null +++ b/1.2/reference/dir_d22c1cb87b72f01e1a7f207eb3bfd1ca.html @@ -0,0 +1,130 @@ + + + + + + + + Crow: include/crow Directory Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow Directory Reference
+
+
+ + +

+Directories

+ + + + + + + +

+Files

file  app.h [code]
 This file includes the definition of the crow::Crow class, the crow::App and crow::SimpleApp aliases, and some macros.
 
file  TinySHA1.hpp [code]
 TinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based on the implementation in boost::uuid::details.
 
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/dir_d22c1cb87b72f01e1a7f207eb3bfd1ca.js b/1.2/reference/dir_d22c1cb87b72f01e1a7f207eb3bfd1ca.js new file mode 100644 index 000000000..58e2aa045 --- /dev/null +++ b/1.2/reference/dir_d22c1cb87b72f01e1a7f207eb3bfd1ca.js @@ -0,0 +1,33 @@ +var dir_d22c1cb87b72f01e1a7f207eb3bfd1ca = +[ + [ "middlewares", "dir_5bc98d550c303c0206de23cf2f7c59bb.html", "dir_5bc98d550c303c0206de23cf2f7c59bb" ], + [ "app.h", "app_8h.html", "app_8h" ], + [ "ci_map.h", "ci__map_8h_source.html", null ], + [ "common.h", "common_8h_source.html", null ], + [ "compression.h", "compression_8h_source.html", null ], + [ "http_connection.h", "http__connection_8h_source.html", null ], + [ "http_parser_merged.h", "http__parser__merged_8h_source.html", null ], + [ "http_request.h", "http__request_8h_source.html", null ], + [ "http_response.h", "http__response_8h_source.html", null ], + [ "http_server.h", "http__server_8h_source.html", null ], + [ "json.h", "json_8h_source.html", null ], + [ "logging.h", "logging_8h_source.html", null ], + [ "middleware.h", "middleware_8h_source.html", null ], + [ "middleware_context.h", "middleware__context_8h_source.html", null ], + [ "mime_types.h", "mime__types_8h_source.html", null ], + [ "multipart.h", "multipart_8h_source.html", null ], + [ "mustache.h", "mustache_8h_source.html", null ], + [ "parser.h", "parser_8h_source.html", null ], + [ "query_string.h", "query__string_8h_source.html", null ], + [ "returnable.h", "returnable_8h_source.html", null ], + [ "routing.h", "routing_8h_source.html", null ], + [ "settings.h", "settings_8h_source.html", null ], + [ "socket_adaptors.h", "socket__adaptors_8h_source.html", null ], + [ "task_timer.h", "task__timer_8h_source.html", null ], + [ "TinySHA1.hpp", "_tiny_s_h_a1_8hpp.html", [ + [ "SHA1", "classsha1_1_1_s_h_a1.html", "classsha1_1_1_s_h_a1" ] + ] ], + [ "utility.h", "utility_8h_source.html", null ], + [ "version.h", "version_8h_source.html", null ], + [ "websocket.h", "websocket_8h_source.html", null ] +]; \ No newline at end of file diff --git a/1.2/reference/dir_d44c64559bbebec7f509842c48db8b23.html b/1.2/reference/dir_d44c64559bbebec7f509842c48db8b23.html new file mode 100644 index 000000000..14384987d --- /dev/null +++ b/1.2/reference/dir_d44c64559bbebec7f509842c48db8b23.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: include Directory Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
include Directory Reference
+
+
+ + +

+Directories

+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/dir_d44c64559bbebec7f509842c48db8b23.js b/1.2/reference/dir_d44c64559bbebec7f509842c48db8b23.js new file mode 100644 index 000000000..3e8acbc7d --- /dev/null +++ b/1.2/reference/dir_d44c64559bbebec7f509842c48db8b23.js @@ -0,0 +1,5 @@ +var dir_d44c64559bbebec7f509842c48db8b23 = +[ + [ "crow", "dir_d22c1cb87b72f01e1a7f207eb3bfd1ca.html", "dir_d22c1cb87b72f01e1a7f207eb3bfd1ca" ], + [ "crow.h", "crow_8h_source.html", null ] +]; \ No newline at end of file diff --git a/1.2/reference/doc.png b/1.2/reference/doc.png new file mode 100644 index 000000000..17edabff9 Binary files /dev/null and b/1.2/reference/doc.png differ diff --git a/1.2/reference/doxygen.css b/1.2/reference/doxygen.css new file mode 100644 index 000000000..ffbff0224 --- /dev/null +++ b/1.2/reference/doxygen.css @@ -0,0 +1,1793 @@ +/* The standard CSS for doxygen 1.9.1 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +p.reference, p.definition { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +ul.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; + column-count: 3; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +th p.starttd, th p.intertd, th p.endtd { + font-size: 100%; + font-weight: 700; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +p.interli { +} + +p.interdd { +} + +p.intertd { +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.navtab { + border-right: 1px solid #A3B4D7; + padding-right: 15px; + text-align: right; + line-height: 110%; +} + +div.navtab table { + border-spacing: 0; +} + +td.navtab { + padding-right: 6px; + padding-left: 6px; +} +td.navtabHL { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + padding-right: 6px; + padding-left: 6px; +} + +td.navtabHL a, td.navtabHL a:visited { + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} + +a.navtab { + font-weight: bold; +} + +div.qindex{ + text-align: center; + width: 100%; + line-height: 140%; + font-size: 130%; + color: #A0A0A0; +} + +dt.alphachar{ + font-size: 180%; + font-weight: bold; +} + +.alphachar a{ + color: black; +} + +.alphachar a:hover, .alphachar a:visited{ + text-decoration: none; +} + +.classindex dl { + padding: 25px; + column-count:1 +} + +.classindex dd { + display:inline-block; + margin-left: 50px; + width: 90%; + line-height: 1.15em; +} + +.classindex dl.odd { + background-color: #F8F9FC; +} + +@media(min-width: 1120px) { + .classindex dl { + column-count:2 + } +} + +@media(min-width: 1320px) { + .classindex dl { + column-count:3 + } +} + + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +.contents a.qindexHL:visited { + color: #FFFFFF; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +ul { + overflow: hidden; /*Fixed: list item bullets overlap floating elements*/ +} + +#side-nav ul { + overflow: visible; /* reset ul rule for scroll bar in GENERATE_TREEVIEW window */ +} + +#main-nav ul { + overflow: visible; /* reset ul rule for the navigation bar drop down lists */ +} + +.fragment { + text-align: left; + direction: ltr; + overflow-x: auto; /*Fixed: fragment lines overlap floating elements*/ + overflow-y: hidden; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 0 0 1px 0; /*Fixed: last line underline overlap border*/ + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line:after { + content:"\000A"; + white-space: pre; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +.lineno { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +div.ah, span.ah { + background-color: black; + font-weight: bold; + color: #FFFFFF; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000 110%); +} + +div.classindex ul { + list-style: none; + padding-left: 0; +} + +div.classindex span.ai { + display: inline-block; +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl, img.inline { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +blockquote.DocNodeRTL { + border-left: 0; + border-right: 2px solid #9CAFD4; + margin: 0 4px 0 24px; + padding: 0 16px 0 12px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight, .memTemplItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtitle { + padding: 8px; + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-image: url('nav_f.png'); + background-repeat: repeat-x; + background-color: #E2E8F2; + line-height: 1.25; + font-weight: 300; + float:left; +} + +.permalink +{ + font-size: 65%; + display: inline-block; + vertical-align: middle; +} + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: 400; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-color: #DFE5F1; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + +} + +.overload { + font-family: "courier new",courier,monospace; + font-size: 65%; +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname, .tparams .paramname, .exception .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype, .tparams .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir, .tparams .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #9CAFD4; + border-bottom: 1px solid #9CAFD4; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +.arrow { + color: #9CAFD4; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} + +.icon { + font-family: Arial, Helvetica; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: #728DC1; + color: white; + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfopen { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderopen.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.iconfclosed { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderclosed.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.icondoc { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('doc.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +table.directory { + font: 400 14px Roboto,sans-serif; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable caption { + caption-side: top; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + font-weight: 400; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +table.classindex +{ + margin: 10px; + white-space: nowrap; + margin-left: 3%; + margin-right: 3%; + width: 94%; + border: 0; + border-spacing: 0; + padding: 0; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +.PageDocRTL-title div.headertitle { + text-align: right; + direction: rtl; +} + +dl { + padding: 0 0 0 0; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug, dl.examples */ +dl.section { + margin-left: 0px; + padding-left: 0px; +} + +dl.section.DocNodeRTL { + margin-right: 0px; + padding-right: 0px; +} + +dl.note { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #D0C000; +} + +dl.note.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #FF0000; +} + +dl.warning.DocNodeRTL, dl.attention.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #00D000; +} + +dl.pre.DocNodeRTL, dl.post.DocNodeRTL, dl.invariant.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #00D000; +} + +dl.deprecated { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #505050; +} + +dl.deprecated.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #505050; +} + +dl.todo { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #00C0E0; +} + +dl.todo.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #00C0E0; +} + +dl.test { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #3030E0; +} + +dl.test.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #3030E0; +} + +dl.bug { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #C08050; +} + +dl.bug.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectalign +{ + vertical-align: middle; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.plantumlgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; + text-align:right; + width:52px; +} + +dl.citelist dd { + margin:2px 0 2px 72px; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 8px 10px 10px; + width: 200px; +} + +.PageDocRTL-title div.toc { + float: left !important; + text-align: right; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +.PageDocRTL-title div.toc li { + background-position-x: right !important; + padding-left: 0 !important; + padding-right: 10px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +span.emoji { + /* font family used at the site: https://unicode.org/emoji/charts/full-emoji-list.html + * font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort; + */ +} + +.PageDocRTL-title div.toc li.level1 { + margin-left: 0 !important; + margin-right: 0; +} + +.PageDocRTL-title div.toc li.level2 { + margin-left: 0 !important; + margin-right: 15px; +} + +.PageDocRTL-title div.toc li.level3 { + margin-left: 0 !important; + margin-right: 30px; +} + +.PageDocRTL-title div.toc li.level4 { + margin-left: 0 !important; + margin-right: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #FFFFFF; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #FFFFFF; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #FFFFFF; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #FFFFFF; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + +/* @group Markdown */ + +table.markdownTable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.markdownTable td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.markdownTable tr { +} + +th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +th.markdownTableHeadLeft, td.markdownTableBodyLeft { + text-align: left +} + +th.markdownTableHeadRight, td.markdownTableBodyRight { + text-align: right +} + +th.markdownTableHeadCenter, td.markdownTableBodyCenter { + text-align: center +} + +.DocNodeRTL { + text-align: right; + direction: rtl; +} + +.DocNodeLTR { + text-align: left; + direction: ltr; +} + +table.DocNodeRTL { + width: auto; + margin-right: 0; + margin-left: auto; +} + +table.DocNodeLTR { + width: auto; + margin-right: auto; + margin-left: 0; +} + +tt, code, kbd, samp +{ + display: inline-block; + direction:ltr; +} +/* @end */ + +u { + text-decoration: underline; +} + diff --git a/1.2/reference/doxygen.svg b/1.2/reference/doxygen.svg new file mode 100644 index 000000000..d42dad52d --- /dev/null +++ b/1.2/reference/doxygen.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/1.2/reference/dynsections.js b/1.2/reference/dynsections.js new file mode 100644 index 000000000..3174bd7be --- /dev/null +++ b/1.2/reference/dynsections.js @@ -0,0 +1,121 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} + +function toggleLevel(level) +{ + $('table.directory tr').each(function() { + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l + + + + + + + Crow: File List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
File List
+
+
+
Here is a list of all documented files with brief descriptions:
+
[detail level 1234]
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  include
  crow
  middlewares
 cookie_parser.h
 cors.h
 session.h
 utf-8.h
 app.hThis file includes the definition of the crow::Crow class, the crow::App and crow::SimpleApp aliases, and some macros
 ci_map.h
 common.h
 compression.h
 http_connection.h
 http_parser_merged.h
 http_request.h
 http_response.h
 http_server.h
 json.h
 logging.h
 middleware.h
 middleware_context.h
 mime_types.h
 multipart.h
 mustache.h
 parser.h
 query_string.h
 returnable.h
 routing.h
 settings.h
 socket_adaptors.h
 task_timer.h
 TinySHA1.hppTinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based on the implementation in boost::uuid::details
 utility.h
 version.h
 websocket.h
 crow.h
+
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/files_dup.js b/1.2/reference/files_dup.js new file mode 100644 index 000000000..f1749d909 --- /dev/null +++ b/1.2/reference/files_dup.js @@ -0,0 +1,4 @@ +var files_dup = +[ + [ "include", "dir_d44c64559bbebec7f509842c48db8b23.html", "dir_d44c64559bbebec7f509842c48db8b23" ] +]; \ No newline at end of file diff --git a/1.2/reference/folderclosed.png b/1.2/reference/folderclosed.png new file mode 100644 index 000000000..bb8ab35ed Binary files /dev/null and b/1.2/reference/folderclosed.png differ diff --git a/1.2/reference/folderopen.png b/1.2/reference/folderopen.png new file mode 100644 index 000000000..d6c7f676a Binary files /dev/null and b/1.2/reference/folderopen.png differ diff --git a/1.2/reference/functions.html b/1.2/reference/functions.html new file mode 100644 index 000000000..36b3a7eb4 --- /dev/null +++ b/1.2/reference/functions.html @@ -0,0 +1,616 @@ + + + + + + + + Crow: Class Members + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
Here is a list of all documented class members with links to the class documentation for each member:
+ +

- a -

+ + +

- b -

+ + +

- c -

+ + +

- d -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- h -

+ + +

- i -

+ + +

- k -

+ + +

- l -

+ + +

- m -

+ + +

- n -

+ + +

- o -

+ + +

- p -

+ + +

- r -

+ + +

- s -

+ + +

- t -

+ + +

- u -

+ + +

- v -

+ + +

- w -

+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/functions_func.html b/1.2/reference/functions_func.html new file mode 100644 index 000000000..364855a54 --- /dev/null +++ b/1.2/reference/functions_func.html @@ -0,0 +1,530 @@ + + + + + + + + Crow: Class Members - Functions + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+  + +

- a -

+ + +

- b -

+ + +

- c -

+ + +

- d -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- h -

+ + +

- i -

+ + +

- l -

+ + +

- m -

+ + +

- n -

+ + +

- o -

+ + +

- p -

+ + +

- r -

+ + +

- s -

+ + +

- t -

+ + +

- u -

+ + +

- v -

+ + +

- w -

+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/functions_type.html b/1.2/reference/functions_type.html new file mode 100644 index 000000000..67eb954b5 --- /dev/null +++ b/1.2/reference/functions_type.html @@ -0,0 +1,123 @@ + + + + + + + + Crow: Class Members - Typedefs + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/functions_vars.html b/1.2/reference/functions_vars.html new file mode 100644 index 000000000..feba7c866 --- /dev/null +++ b/1.2/reference/functions_vars.html @@ -0,0 +1,189 @@ + + + + + + + + Crow: Class Members - Variables + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/globals.html b/1.2/reference/globals.html new file mode 100644 index 000000000..1c9109c39 --- /dev/null +++ b/1.2/reference/globals.html @@ -0,0 +1,132 @@ + + + + + + + + Crow: File Members + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
Here is a list of all documented file members with links to the documentation:
    +
  • CROW_BP_CATCHALL_ROUTE +: app.h +
  • +
  • CROW_BP_ROUTE +: app.h +
  • +
  • CROW_CATCHALL_ROUTE +: app.h +
  • +
  • CROW_MIDDLEWARES +: app.h +
  • +
  • CROW_ROUTE +: app.h +
  • +
  • CROW_WEBSOCKET_ROUTE +: app.h +
  • +
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/globals_defs.html b/1.2/reference/globals_defs.html new file mode 100644 index 000000000..1c47eba14 --- /dev/null +++ b/1.2/reference/globals_defs.html @@ -0,0 +1,132 @@ + + + + + + + + Crow: File Members + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
    +
  • CROW_BP_CATCHALL_ROUTE +: app.h +
  • +
  • CROW_BP_ROUTE +: app.h +
  • +
  • CROW_CATCHALL_ROUTE +: app.h +
  • +
  • CROW_MIDDLEWARES +: app.h +
  • +
  • CROW_ROUTE +: app.h +
  • +
  • CROW_WEBSOCKET_ROUTE +: app.h +
  • +
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/hierarchy.html b/1.2/reference/hierarchy.html new file mode 100644 index 000000000..dc69e3083 --- /dev/null +++ b/1.2/reference/hierarchy.html @@ -0,0 +1,230 @@ + + + + + + + + Crow: Class Hierarchy + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Class Hierarchy
+
+
+
This inheritance list is sorted roughly, but not completely, alphabetically:
+
[detail level 123]
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Ccrow::mustache::Action
 Ccrow::BaseRuleA base class for all rules
 Ccrow::BlueprintA blueprint can be considered a smaller section of a Crow app, specifically where the router is conecerned
 Ccrow::session::CachedSessionCachedSessions are shared across requests
 Ccrow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, S1, S2 >
 Ccrow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< double, Args1... >, black_magic::S< Args2... > >
 Ccrow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< int64_t, Args1... >, black_magic::S< Args2... > >
 Ccrow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< std::string, Args1... >, black_magic::S< Args2... > >
 Ccrow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< uint64_t, Args1... >, black_magic::S< Args2... > >
 Ccrow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S< Args1... > >
 Ccrow::detail::routing_handler_call_helper::call_pair< T, Pos >
 Ccrow::detail::routing_handler_call_helper::call_params< H1 >
 Ccrow::CatchallRule
 Ccrow::detail::check_after_handle_arity_3< MW >
 Ccrow::detail::check_after_handle_arity_3_const< MW >
 Ccrow::detail::check_before_handle_arity_3< MW >
 Ccrow::detail::check_before_handle_arity_3_const< MW >
 Ccrow::detail::check_global_call_false< MW >
 Ccrow::ci_hashHashing function for ci_map (unordered_multimap)
 Ccrow::ci_key_eqEquals function for ci_map (unordered_multimap)
 Ccrow::websocket::connectionA base class for websocket connection
 Cblack_magic::last_element_type::type::context
 Ccrow::CookieParser::context
 Ccrow::CORSHandler::context
 Ccrow::SessionMiddleware< Store >::context
 Ccrow::UTF8::context
 Ccrow::CookieParser::Cookie
 Ccrow::CookieParser
 Ccrow::CORSHandlerCORSHandler is a global middleware for setting CORS headers
 Ccrow::CORSRulesUsed for tuning CORS policies
 Ccrow::Crow< Middlewares >The main server application class
 Cstd::enable_shared_from_this
 Cstd::exceptionSTL class
 Ccrow::session::ExpirationTrackerExpiration tracker keeps track of soonest-to-expire keys
 Ccrow::FileStore
 Ccrow::detail::check_after_handle_arity_3< MW >::get< T, >
 Ccrow::detail::check_after_handle_arity_3_const< MW >::get< T, const >
 Ccrow::detail::check_before_handle_arity_3< MW >::get< T, >
 Ccrow::detail::check_before_handle_arity_3_const< MW >::get< T, const >
 Ccrow::detail::check_global_call_false< MW >::get< T, type >
 Ccrow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< Args >
 Ccrow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< ArgsWrapped... >
 Ccrow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< const request &, Args... >
 Ccrow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< const request &, response &, Args... >
 Ccrow::multipart::headerThe first part in a section, contains metadata about the part
 Ccrow::http_parser
 Ccrow::http_parser_settings
 Ccrow::ILocalMiddlewareLocal middleware should extend ILocalMiddleware
 Ccrow::ILogHandler
 Ccrow::InMemoryStoreInMemoryStore stores all entries in memory
 Ccrow::detail::is_after_handle_arity_3_impl< T >
 Ccrow::detail::is_before_handle_arity_3_impl< T >
 Ccrow::detail::is_middleware_global< MW >
 Ccrow::logger
 Ccrow::detail::middleware_call_criteria_dynamic< Reversed >
 Ccrow::detail::middleware_call_criteria_dynamic< false >
 Ccrow::detail::middleware_call_criteria_dynamic< true >
 Ccrow::detail::middleware_call_criteria_only_global
 Ccrow::detail::middleware_indicesTypesafe wrapper for storing lists of middleware as their indices in the App
 Ccrow::session::multi_value
 Ccrow::Trie::Node
 Ccrow::multipart::partOne part of the multipart message
 Ccrow::detail::partial_context<>
 Ccrow::query_stringA class to represent any data coming after the ? in the request URL into key-value pairs
 Ccrow::json::detail::r_stringA read string implementation with comparison functionality
 Ccrow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::req_handler_wrapper< Req, Args >
 Ccrow::requestAn HTTP request
 Ccrow::responseHTTP response
 Ccrow::returnableAn abstract class that allows any other class to be returned by a handler
 Ccrow::RouterHandles matching requests to existing rules and upgrade requests
 Ccrow::routing_handle_result
 Ccrow::RuleParameterTraits< T >Allows the user to assign parameters using functions
 Ccrow::RuleParameterTraits< DynamicRule >
 Ccrow::RuleParameterTraits< TaggedRule< Args... > >
 Ccrow::json::rvalueJSON read value
 Ccrow::websocket::Connection< Adaptor, Handler >::SendMessageType
 Ccrow::Server< Handler, Adaptor, Middlewares >
 Ccrow::SessionMiddleware< Store >
 Csha1::SHA1A tiny SHA1 algorithm implementation used internally in the Crow server (specifically in crow/websocket.h)
 Ccrow::SocketAdaptorA wrapper for the asio::ip::tcp::socket and asio::ssl::stream
 Ccrow::SSLAdaptor
 Ccrow::response::static_file_infoThis constains metadata (coming from the stat command) related to any static files associated with this response
 Ccrow::detail::task_timerA class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 second
 Cblack_magic::pop_back::template rebind
 Ccrow::mustache::template_tA mustache template object
 Ccrow::TrieA search tree
 Ccrow::UTF8
 Ccrow::websocket::Connection< Adaptor, Handler >::WeakWrappedMessage< Callable >
 Ccrow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >
 Ccrow::json::wvalue_reader
+
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/hierarchy.js b/1.2/reference/hierarchy.js new file mode 100644 index 000000000..e3e1da227 --- /dev/null +++ b/1.2/reference/hierarchy.js @@ -0,0 +1,125 @@ +var hierarchy = +[ + [ "crow::mustache::Action", "structcrow_1_1mustache_1_1_action.html", null ], + [ "crow::BaseRule", "classcrow_1_1_base_rule.html", [ + [ "crow::DynamicRule", "classcrow_1_1_dynamic_rule.html", null ], + [ "crow::TaggedRule< Args >", "classcrow_1_1_tagged_rule.html", null ], + [ "crow::WebSocketRule< App >", "classcrow_1_1_web_socket_rule.html", null ] + ] ], + [ "crow::Blueprint", "classcrow_1_1_blueprint.html", null ], + [ "crow::session::CachedSession", "structcrow_1_1session_1_1_cached_session.html", null ], + [ "crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, S1, S2 >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call.html", null ], + [ "crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< double, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.html", null ], + [ "crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< int64_t, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.html", null ], + [ "crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< std::string, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.html", null ], + [ "crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< uint64_t, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.html", null ], + [ "crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S< Args1... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.html", null ], + [ "crow::detail::routing_handler_call_helper::call_pair< T, Pos >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.html", null ], + [ "crow::detail::routing_handler_call_helper::call_params< H1 >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html", null ], + [ "crow::CatchallRule", "classcrow_1_1_catchall_rule.html", null ], + [ "crow::detail::check_after_handle_arity_3< MW >", "structcrow_1_1detail_1_1check__after__handle__arity__3.html", null ], + [ "crow::detail::check_after_handle_arity_3_const< MW >", "structcrow_1_1detail_1_1check__after__handle__arity__3__const.html", null ], + [ "crow::detail::check_before_handle_arity_3< MW >", "structcrow_1_1detail_1_1check__before__handle__arity__3.html", null ], + [ "crow::detail::check_before_handle_arity_3_const< MW >", "structcrow_1_1detail_1_1check__before__handle__arity__3__const.html", null ], + [ "crow::detail::check_global_call_false< MW >", "structcrow_1_1detail_1_1check__global__call__false.html", null ], + [ "crow::ci_hash", "structcrow_1_1ci__hash.html", null ], + [ "crow::ci_key_eq", "structcrow_1_1ci__key__eq.html", null ], + [ "crow::websocket::connection", "structcrow_1_1websocket_1_1connection.html", [ + [ "crow::websocket::Connection< Adaptor, Handler >", "classcrow_1_1websocket_1_1_connection.html", null ] + ] ], + [ "black_magic::last_element_type::type::context", null, [ + [ "crow::detail::partial_context< Middlewares... >", "structcrow_1_1detail_1_1partial__context.html", [ + [ "crow::detail::context< Middlewares... >", "structcrow_1_1detail_1_1context.html", null ], + [ "crow::detail::context< Middlewares >", "structcrow_1_1detail_1_1context.html", null ] + ] ], + [ "crow::detail::partial_context< Middlewares >", "structcrow_1_1detail_1_1partial__context.html", null ] + ] ], + [ "crow::CookieParser::context", "structcrow_1_1_cookie_parser_1_1context.html", null ], + [ "crow::CORSHandler::context", "structcrow_1_1_c_o_r_s_handler_1_1context.html", null ], + [ "crow::SessionMiddleware< Store >::context", "structcrow_1_1_session_middleware_1_1context.html", null ], + [ "crow::UTF8::context", "structcrow_1_1_u_t_f8_1_1context.html", null ], + [ "crow::CookieParser::Cookie", "structcrow_1_1_cookie_parser_1_1_cookie.html", null ], + [ "crow::CookieParser", "structcrow_1_1_cookie_parser.html", null ], + [ "crow::CORSHandler", "structcrow_1_1_c_o_r_s_handler.html", null ], + [ "crow::CORSRules", "structcrow_1_1_c_o_r_s_rules.html", null ], + [ "crow::Crow< Middlewares >", "classcrow_1_1_crow.html", null ], + [ "std::enable_shared_from_this", null, [ + [ "crow::Connection< Adaptor, Handler, Middlewares >", "classcrow_1_1_connection.html", null ] + ] ], + [ "std::exception", null, [ + [ "crow::mustache::invalid_template_exception", "classcrow_1_1mustache_1_1invalid__template__exception.html", null ] + ] ], + [ "crow::session::ExpirationTracker", "structcrow_1_1session_1_1_expiration_tracker.html", null ], + [ "crow::FileStore", "structcrow_1_1_file_store.html", null ], + [ "crow::detail::check_after_handle_arity_3< MW >::get< T, >", "structcrow_1_1detail_1_1check__after__handle__arity__3_1_1get.html", null ], + [ "crow::detail::check_after_handle_arity_3_const< MW >::get< T, const >", "structcrow_1_1detail_1_1check__after__handle__arity__3__const_1_1get.html", null ], + [ "crow::detail::check_before_handle_arity_3< MW >::get< T, >", "structcrow_1_1detail_1_1check__before__handle__arity__3_1_1get.html", null ], + [ "crow::detail::check_before_handle_arity_3_const< MW >::get< T, const >", "structcrow_1_1detail_1_1check__before__handle__arity__3__const_1_1get.html", null ], + [ "crow::detail::check_global_call_false< MW >::get< T, type >", "structcrow_1_1detail_1_1check__global__call__false_1_1get.html", null ], + [ "crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< Args >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html", null ], + [ "crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< ArgsWrapped... >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html", null ], + [ "crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< const request &, Args... >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.html", null ], + [ "crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< const request &, response &, Args... >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.html", null ], + [ "crow::multipart::header", "structcrow_1_1multipart_1_1header.html", null ], + [ "crow::http_parser", "structcrow_1_1http__parser.html", [ + [ "crow::HTTPParser< crow::Connection >", "structcrow_1_1_h_t_t_p_parser.html", null ], + [ "crow::HTTPParser< Handler >", "structcrow_1_1_h_t_t_p_parser.html", null ] + ] ], + [ "crow::http_parser_settings", "structcrow_1_1http__parser__settings.html", null ], + [ "crow::ILocalMiddleware", "structcrow_1_1_i_local_middleware.html", null ], + [ "crow::ILogHandler", "classcrow_1_1_i_log_handler.html", [ + [ "crow::CerrLogHandler", "classcrow_1_1_cerr_log_handler.html", null ] + ] ], + [ "crow::InMemoryStore", "structcrow_1_1_in_memory_store.html", null ], + [ "crow::detail::is_after_handle_arity_3_impl< T >", "structcrow_1_1detail_1_1is__after__handle__arity__3__impl.html", null ], + [ "crow::detail::is_before_handle_arity_3_impl< T >", "structcrow_1_1detail_1_1is__before__handle__arity__3__impl.html", null ], + [ "crow::detail::is_middleware_global< MW >", "structcrow_1_1detail_1_1is__middleware__global.html", null ], + [ "crow::logger", "classcrow_1_1logger.html", null ], + [ "crow::detail::middleware_call_criteria_dynamic< Reversed >", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic.html", null ], + [ "crow::detail::middleware_call_criteria_dynamic< false >", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.html", null ], + [ "crow::detail::middleware_call_criteria_dynamic< true >", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.html", null ], + [ "crow::detail::middleware_call_criteria_only_global", "structcrow_1_1detail_1_1middleware__call__criteria__only__global.html", null ], + [ "crow::detail::middleware_indices", "structcrow_1_1detail_1_1middleware__indices.html", null ], + [ "crow::session::multi_value", "structcrow_1_1session_1_1multi__value.html", null ], + [ "crow::Trie::Node", "structcrow_1_1_trie_1_1_node.html", null ], + [ "crow::multipart::part", "structcrow_1_1multipart_1_1part.html", null ], + [ "crow::detail::partial_context<>", "structcrow_1_1detail_1_1partial__context_3_4.html", null ], + [ "crow::query_string", "classcrow_1_1query__string.html", null ], + [ "crow::json::detail::r_string", "structcrow_1_1json_1_1detail_1_1r__string.html", null ], + [ "crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::req_handler_wrapper< Req, Args >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.html", null ], + [ "crow::request", "structcrow_1_1request.html", null ], + [ "crow::response", "structcrow_1_1response.html", null ], + [ "crow::returnable", "structcrow_1_1returnable.html", [ + [ "crow::json::wvalue", "classcrow_1_1json_1_1wvalue.html", null ], + [ "crow::multipart::message", "structcrow_1_1multipart_1_1message.html", null ], + [ "crow::mustache::rendered_template", "structcrow_1_1mustache_1_1rendered__template.html", null ] + ] ], + [ "crow::Router", "classcrow_1_1_router.html", null ], + [ "crow::routing_handle_result", "structcrow_1_1routing__handle__result.html", null ], + [ "crow::RuleParameterTraits< T >", "structcrow_1_1_rule_parameter_traits.html", null ], + [ "crow::RuleParameterTraits< DynamicRule >", "structcrow_1_1_rule_parameter_traits.html", [ + [ "crow::DynamicRule", "classcrow_1_1_dynamic_rule.html", null ] + ] ], + [ "crow::RuleParameterTraits< TaggedRule< Args... > >", "structcrow_1_1_rule_parameter_traits.html", [ + [ "crow::TaggedRule< Args >", "classcrow_1_1_tagged_rule.html", null ] + ] ], + [ "crow::json::rvalue", "classcrow_1_1json_1_1rvalue.html", null ], + [ "crow::websocket::Connection< Adaptor, Handler >::SendMessageType", "structcrow_1_1websocket_1_1_connection_1_1_send_message_type.html", null ], + [ "crow::Server< Handler, Adaptor, Middlewares >", "classcrow_1_1_server.html", null ], + [ "crow::SessionMiddleware< Store >", "structcrow_1_1_session_middleware.html", null ], + [ "sha1::SHA1", "classsha1_1_1_s_h_a1.html", null ], + [ "crow::SocketAdaptor", "structcrow_1_1_socket_adaptor.html", null ], + [ "crow::SSLAdaptor", "structcrow_1_1_s_s_l_adaptor.html", null ], + [ "crow::response::static_file_info", "structcrow_1_1response_1_1static__file__info.html", null ], + [ "crow::detail::task_timer", "classcrow_1_1detail_1_1task__timer.html", null ], + [ "black_magic::pop_back::template rebind", null, [ + [ "crow::detail::partial_context< Middlewares... >", "structcrow_1_1detail_1_1partial__context.html", null ], + [ "crow::detail::partial_context< Middlewares >", "structcrow_1_1detail_1_1partial__context.html", null ] + ] ], + [ "crow::mustache::template_t", "classcrow_1_1mustache_1_1template__t.html", null ], + [ "crow::Trie", "classcrow_1_1_trie.html", null ], + [ "crow::UTF8", "structcrow_1_1_u_t_f8.html", null ], + [ "crow::websocket::Connection< Adaptor, Handler >::WeakWrappedMessage< Callable >", "structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.html", null ], + [ "crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html", null ], + [ "crow::json::wvalue_reader", "structcrow_1_1json_1_1wvalue__reader.html", null ] +]; \ No newline at end of file diff --git a/1.2/reference/http__connection_8h_source.html b/1.2/reference/http__connection_8h_source.html new file mode 100644 index 000000000..2e39758f8 --- /dev/null +++ b/1.2/reference/http__connection_8h_source.html @@ -0,0 +1,766 @@ + + + + + + + + Crow: include/crow/http_connection.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
http_connection.h
+
+
+
1 #pragma once
+
2 
+
3 #ifdef CROW_USE_BOOST
+
4 #include <boost/asio.hpp>
+
5 #else
+
6 #ifndef ASIO_STANDALONE
+
7 #define ASIO_STANDALONE
+
8 #endif
+
9 #include <asio.hpp>
+
10 #endif
+
11 
+
12 #include <algorithm>
+
13 #include <atomic>
+
14 #include <chrono>
+
15 #include <memory>
+
16 #include <vector>
+
17 
+
18 #include "crow/http_parser_merged.h"
+
19 #include "crow/common.h"
+
20 #include "crow/compression.h"
+
21 #include "crow/http_response.h"
+
22 #include "crow/logging.h"
+
23 #include "crow/middleware.h"
+
24 #include "crow/middleware_context.h"
+
25 #include "crow/parser.h"
+
26 #include "crow/settings.h"
+
27 #include "crow/socket_adaptors.h"
+
28 #include "crow/task_timer.h"
+
29 #include "crow/utility.h"
+
30 
+
31 namespace crow
+
32 {
+
33 #ifdef CROW_USE_BOOST
+
34  namespace asio = boost::asio;
+
35  using error_code = boost::system::error_code;
+
36 #else
+
37  using error_code = asio::error_code;
+
38 #endif
+
39  using tcp = asio::ip::tcp;
+
40 
+
41 #ifdef CROW_ENABLE_DEBUG
+
42  static std::atomic<int> connectionCount;
+
43 #endif
+
44 
+
45  /// An HTTP connection.
+
46  template<typename Adaptor, typename Handler, typename... Middlewares>
+
47  class Connection: public std::enable_shared_from_this<Connection<Adaptor, Handler, Middlewares...>>
+
48  {
+
49  friend struct crow::response;
+
50 
+
51  public:
+
52  Connection(
+
53  asio::io_service& io_service,
+
54  Handler* handler,
+
55  const std::string& server_name,
+
56  std::tuple<Middlewares...>* middlewares,
+
57  std::function<std::string()>& get_cached_date_str_f,
+
58  detail::task_timer& task_timer,
+
59  typename Adaptor::context* adaptor_ctx_,
+
60  std::atomic<unsigned int>& queue_length):
+
61  adaptor_(io_service, adaptor_ctx_),
+
62  handler_(handler),
+
63  parser_(this),
+
64  req_(parser_.req),
+
65  server_name_(server_name),
+
66  middlewares_(middlewares),
+
67  get_cached_date_str(get_cached_date_str_f),
+
68  task_timer_(task_timer),
+
69  res_stream_threshold_(handler->stream_threshold()),
+
70  queue_length_(queue_length)
+
71  {
+
72 #ifdef CROW_ENABLE_DEBUG
+
73  connectionCount++;
+
74  CROW_LOG_DEBUG << "Connection (" << this << ") allocated, total: " << connectionCount;
+
75 #endif
+
76  }
+
77 
+
78  ~Connection()
+
79  {
+
80 #ifdef CROW_ENABLE_DEBUG
+
81  connectionCount--;
+
82  CROW_LOG_DEBUG << "Connection (" << this << ") freed, total: " << connectionCount;
+
83 #endif
+
84  }
+
85 
+
86  /// The TCP socket on top of which the connection is established.
+
87  decltype(std::declval<Adaptor>().raw_socket())& socket()
+
88  {
+
89  return adaptor_.raw_socket();
+
90  }
+
91 
+
92  void start()
+
93  {
+
94  auto self = this->shared_from_this();
+
95  adaptor_.start([self](const error_code& ec) {
+
96  if (!ec)
+
97  {
+
98  self->start_deadline();
+
99  self->parser_.clear();
+
100 
+
101  self->do_read();
+
102  }
+
103  else
+
104  {
+
105  CROW_LOG_ERROR << "Could not start adaptor: " << ec.message();
+
106  }
+
107  });
+
108  }
+
109 
+
110  void handle_url()
+
111  {
+
112  routing_handle_result_ = handler_->handle_initial(req_, res);
+
113  // if no route is found for the request method, return the response without parsing or processing anything further.
+
114  if (!routing_handle_result_->rule_index)
+
115  {
+
116  parser_.done();
+
117  need_to_call_after_handlers_ = true;
+ +
119  }
+
120  }
+
121 
+
122  void handle_header()
+
123  {
+
124  // HTTP 1.1 Expect: 100-continue
+
125  if (req_.http_ver_major == 1 && req_.http_ver_minor == 1 && get_header_value(req_.headers, "expect") == "100-continue")
+
126  {
+
127  continue_requested = true;
+
128  buffers_.clear();
+
129  static std::string expect_100_continue = "HTTP/1.1 100 Continue\r\n\r\n";
+
130  buffers_.emplace_back(expect_100_continue.data(), expect_100_continue.size());
+
131  do_write();
+
132  }
+
133  }
+
134 
+
135  void handle()
+
136  {
+
137  // TODO(EDev): cancel_deadline_timer should be looked into, it might be a good idea to add it to handle_url() and then restart the timer once everything passes
+
138  cancel_deadline_timer();
+
139  bool is_invalid_request = false;
+
140  add_keep_alive_ = false;
+
141 
+
142  // Create context
+
143  ctx_ = detail::context<Middlewares...>();
+
144  req_.middleware_context = static_cast<void*>(&ctx_);
+
145  req_.middleware_container = static_cast<void*>(middlewares_);
+
146  req_.io_service = &adaptor_.get_io_service();
+
147 
+
148  req_.remote_ip_address = adaptor_.remote_endpoint().address().to_string();
+
149 
+
150  add_keep_alive_ = req_.keep_alive;
+
151  close_connection_ = req_.close_connection;
+
152 
+
153  if (req_.check_version(1, 1)) // HTTP/1.1
+
154  {
+
155  if (!req_.headers.count("host"))
+
156  {
+
157  is_invalid_request = true;
+
158  res = response(400);
+
159  }
+
160  else if (req_.upgrade)
+
161  {
+
162  // h2 or h2c headers
+
163  if (req_.get_header_value("upgrade").substr(0, 2) == "h2")
+
164  {
+
165  // TODO(ipkn): HTTP/2
+
166  // currently, ignore upgrade header
+
167  }
+
168  else
+
169  {
+
170 
+
171  detail::middleware_call_helper<detail::middleware_call_criteria_only_global,
+
172  0, decltype(ctx_), decltype(*middlewares_)>({}, *middlewares_, req_, res, ctx_);
+
173  close_connection_ = true;
+
174  handler_->handle_upgrade(req_, res, std::move(adaptor_));
+
175  return;
+
176  }
+
177  }
+
178  }
+
179 
+
180  CROW_LOG_INFO << "Request: " << utility::lexical_cast<std::string>(adaptor_.remote_endpoint()) << " " << this << " HTTP/" << (char)(req_.http_ver_major + '0') << "." << (char)(req_.http_ver_minor + '0') << ' ' << method_name(req_.method) << " " << req_.url;
+
181 
+
182 
+
183  need_to_call_after_handlers_ = false;
+
184  if (!is_invalid_request)
+
185  {
+
186  res.complete_request_handler_ = nullptr;
+
187  auto self = this->shared_from_this();
+
188  res.is_alive_helper_ = [self]() -> bool {
+
189  return self->adaptor_.is_open();
+
190  };
+
191 
+
192  detail::middleware_call_helper<detail::middleware_call_criteria_only_global,
+
193  0, decltype(ctx_), decltype(*middlewares_)>({}, *middlewares_, req_, res, ctx_);
+
194 
+
195  if (!res.completed_)
+
196  {
+
197  auto self = this->shared_from_this();
+
198  res.complete_request_handler_ = [self] {
+
199  self->complete_request();
+
200  };
+
201  need_to_call_after_handlers_ = true;
+
202  handler_->handle(req_, res, routing_handle_result_);
+
203  if (add_keep_alive_)
+
204  res.set_header("connection", "Keep-Alive");
+
205  }
+
206  else
+
207  {
+ +
209  }
+
210  }
+
211  else
+
212  {
+ +
214  }
+
215  }
+
216 
+
217  /// Call the after handle middleware and send the write the response to the connection.
+ +
219  {
+
220  CROW_LOG_INFO << "Response: " << this << ' ' << req_.raw_url << ' ' << res.code << ' ' << close_connection_;
+
221  res.is_alive_helper_ = nullptr;
+
222 
+
223  if (need_to_call_after_handlers_)
+
224  {
+
225  need_to_call_after_handlers_ = false;
+
226 
+
227  // call all after_handler of middlewares
+
228  detail::after_handlers_call_helper<
+ +
230  (static_cast<int>(sizeof...(Middlewares)) - 1),
+
231  decltype(ctx_),
+
232  decltype(*middlewares_)>({}, *middlewares_, ctx_, req_, res);
+
233  }
+
234 #ifdef CROW_ENABLE_COMPRESSION
+
235  if (handler_->compression_used())
+
236  {
+
237  std::string accept_encoding = req_.get_header_value("Accept-Encoding");
+
238  if (!accept_encoding.empty() && res.compressed)
+
239  {
+
240  switch (handler_->compression_algorithm())
+
241  {
+
242  case compression::DEFLATE:
+
243  if (accept_encoding.find("deflate") != std::string::npos)
+
244  {
+
245  res.body = compression::compress_string(res.body, compression::algorithm::DEFLATE);
+
246  res.set_header("Content-Encoding", "deflate");
+
247  }
+
248  break;
+
249  case compression::GZIP:
+
250  if (accept_encoding.find("gzip") != std::string::npos)
+
251  {
+
252  res.body = compression::compress_string(res.body, compression::algorithm::GZIP);
+
253  res.set_header("Content-Encoding", "gzip");
+
254  }
+
255  break;
+
256  default:
+
257  break;
+
258  }
+
259  }
+
260  }
+
261 #endif
+
262  //if there is a redirection with a partial URL, treat the URL as a route.
+
263  std::string location = res.get_header_value("Location");
+
264  if (!location.empty() && location.find("://", 0) == std::string::npos)
+
265  {
+
266 #ifdef CROW_ENABLE_SSL
+
267  if (handler_->ssl_used())
+
268  location.insert(0, "https://" + req_.get_header_value("Host"));
+
269  else
+
270 #endif
+
271  location.insert(0, "http://" + req_.get_header_value("Host"));
+
272  res.set_header("location", location);
+
273  }
+
274 
+
275  prepare_buffers();
+
276 
+
277  if (res.is_static_type())
+
278  {
+
279  do_write_static();
+
280  }
+
281  else
+
282  {
+
283  do_write_general();
+
284  }
+
285  }
+
286 
+
287  private:
+
288  void prepare_buffers()
+
289  {
+
290  res.complete_request_handler_ = nullptr;
+
291  res.is_alive_helper_ = nullptr;
+
292 
+
293  if (!adaptor_.is_open())
+
294  {
+
295  //CROW_LOG_DEBUG << this << " delete (socket is closed) " << is_reading << ' ' << is_writing;
+
296  //delete this;
+
297  return;
+
298  }
+
299  // TODO(EDev): HTTP version in status codes should be dynamic
+
300  // Keep in sync with common.h/status
+
301  static std::unordered_map<int, std::string> statusCodes = {
+
302  {status::CONTINUE, "HTTP/1.1 100 Continue\r\n"},
+
303  {status::SWITCHING_PROTOCOLS, "HTTP/1.1 101 Switching Protocols\r\n"},
+
304 
+
305  {status::OK, "HTTP/1.1 200 OK\r\n"},
+
306  {status::CREATED, "HTTP/1.1 201 Created\r\n"},
+
307  {status::ACCEPTED, "HTTP/1.1 202 Accepted\r\n"},
+
308  {status::NON_AUTHORITATIVE_INFORMATION, "HTTP/1.1 203 Non-Authoritative Information\r\n"},
+
309  {status::NO_CONTENT, "HTTP/1.1 204 No Content\r\n"},
+
310  {status::RESET_CONTENT, "HTTP/1.1 205 Reset Content\r\n"},
+
311  {status::PARTIAL_CONTENT, "HTTP/1.1 206 Partial Content\r\n"},
+
312 
+
313  {status::MULTIPLE_CHOICES, "HTTP/1.1 300 Multiple Choices\r\n"},
+
314  {status::MOVED_PERMANENTLY, "HTTP/1.1 301 Moved Permanently\r\n"},
+
315  {status::FOUND, "HTTP/1.1 302 Found\r\n"},
+
316  {status::SEE_OTHER, "HTTP/1.1 303 See Other\r\n"},
+
317  {status::NOT_MODIFIED, "HTTP/1.1 304 Not Modified\r\n"},
+
318  {status::TEMPORARY_REDIRECT, "HTTP/1.1 307 Temporary Redirect\r\n"},
+
319  {status::PERMANENT_REDIRECT, "HTTP/1.1 308 Permanent Redirect\r\n"},
+
320 
+
321  {status::BAD_REQUEST, "HTTP/1.1 400 Bad Request\r\n"},
+
322  {status::UNAUTHORIZED, "HTTP/1.1 401 Unauthorized\r\n"},
+
323  {status::FORBIDDEN, "HTTP/1.1 403 Forbidden\r\n"},
+
324  {status::NOT_FOUND, "HTTP/1.1 404 Not Found\r\n"},
+
325  {status::METHOD_NOT_ALLOWED, "HTTP/1.1 405 Method Not Allowed\r\n"},
+
326  {status::NOT_ACCEPTABLE, "HTTP/1.1 406 Not Acceptable\r\n"},
+
327  {status::PROXY_AUTHENTICATION_REQUIRED, "HTTP/1.1 407 Proxy Authentication Required\r\n"},
+
328  {status::CONFLICT, "HTTP/1.1 409 Conflict\r\n"},
+
329  {status::GONE, "HTTP/1.1 410 Gone\r\n"},
+
330  {status::PAYLOAD_TOO_LARGE, "HTTP/1.1 413 Payload Too Large\r\n"},
+
331  {status::UNSUPPORTED_MEDIA_TYPE, "HTTP/1.1 415 Unsupported Media Type\r\n"},
+
332  {status::RANGE_NOT_SATISFIABLE, "HTTP/1.1 416 Range Not Satisfiable\r\n"},
+
333  {status::EXPECTATION_FAILED, "HTTP/1.1 417 Expectation Failed\r\n"},
+
334  {status::PRECONDITION_REQUIRED, "HTTP/1.1 428 Precondition Required\r\n"},
+
335  {status::TOO_MANY_REQUESTS, "HTTP/1.1 429 Too Many Requests\r\n"},
+
336  {status::UNAVAILABLE_FOR_LEGAL_REASONS, "HTTP/1.1 451 Unavailable For Legal Reasons\r\n"},
+
337 
+
338  {status::INTERNAL_SERVER_ERROR, "HTTP/1.1 500 Internal Server Error\r\n"},
+
339  {status::NOT_IMPLEMENTED, "HTTP/1.1 501 Not Implemented\r\n"},
+
340  {status::BAD_GATEWAY, "HTTP/1.1 502 Bad Gateway\r\n"},
+
341  {status::SERVICE_UNAVAILABLE, "HTTP/1.1 503 Service Unavailable\r\n"},
+
342  {status::GATEWAY_TIMEOUT, "HTTP/1.1 504 Gateway Timeout\r\n"},
+
343  {status::VARIANT_ALSO_NEGOTIATES, "HTTP/1.1 506 Variant Also Negotiates\r\n"},
+
344  };
+
345 
+
346  static const std::string seperator = ": ";
+
347 
+
348  buffers_.clear();
+
349  buffers_.reserve(4 * (res.headers.size() + 5) + 3);
+
350 
+
351  if (!statusCodes.count(res.code))
+
352  {
+
353  CROW_LOG_WARNING << this << " status code "
+
354  << "(" << res.code << ")"
+
355  << " not defined, returning 500 instead";
+
356  res.code = 500;
+
357  }
+
358 
+
359  auto& status = statusCodes.find(res.code)->second;
+
360  buffers_.emplace_back(status.data(), status.size());
+
361 
+
362  if (res.code >= 400 && res.body.empty())
+
363  res.body = statusCodes[res.code].substr(9);
+
364 
+
365  for (auto& kv : res.headers)
+
366  {
+
367  buffers_.emplace_back(kv.first.data(), kv.first.size());
+
368  buffers_.emplace_back(seperator.data(), seperator.size());
+
369  buffers_.emplace_back(kv.second.data(), kv.second.size());
+
370  buffers_.emplace_back(crlf.data(), crlf.size());
+
371  }
+
372 
+
373  if (!res.manual_length_header && !res.headers.count("content-length"))
+
374  {
+
375  content_length_ = std::to_string(res.body.size());
+
376  static std::string content_length_tag = "Content-Length: ";
+
377  buffers_.emplace_back(content_length_tag.data(), content_length_tag.size());
+
378  buffers_.emplace_back(content_length_.data(), content_length_.size());
+
379  buffers_.emplace_back(crlf.data(), crlf.size());
+
380  }
+
381  if (!res.headers.count("server"))
+
382  {
+
383  static std::string server_tag = "Server: ";
+
384  buffers_.emplace_back(server_tag.data(), server_tag.size());
+
385  buffers_.emplace_back(server_name_.data(), server_name_.size());
+
386  buffers_.emplace_back(crlf.data(), crlf.size());
+
387  }
+
388  if (!res.headers.count("date"))
+
389  {
+
390  static std::string date_tag = "Date: ";
+
391  date_str_ = get_cached_date_str();
+
392  buffers_.emplace_back(date_tag.data(), date_tag.size());
+
393  buffers_.emplace_back(date_str_.data(), date_str_.size());
+
394  buffers_.emplace_back(crlf.data(), crlf.size());
+
395  }
+
396  if (add_keep_alive_)
+
397  {
+
398  static std::string keep_alive_tag = "Connection: Keep-Alive";
+
399  buffers_.emplace_back(keep_alive_tag.data(), keep_alive_tag.size());
+
400  buffers_.emplace_back(crlf.data(), crlf.size());
+
401  }
+
402 
+
403  buffers_.emplace_back(crlf.data(), crlf.size());
+
404  }
+
405 
+
406  void do_write_static()
+
407  {
+
408  asio::write(adaptor_.socket(), buffers_);
+
409 
+
410  if (res.file_info.statResult == 0)
+
411  {
+
412  std::ifstream is(res.file_info.path.c_str(), std::ios::in | std::ios::binary);
+
413  std::vector<asio::const_buffer> buffers{1};
+
414  char buf[16384];
+
415  is.read(buf, sizeof(buf));
+
416  while (is.gcount() > 0)
+
417  {
+
418  buffers[0] = asio::buffer(buf, is.gcount());
+
419  do_write_sync(buffers);
+
420  is.read(buf, sizeof(buf));
+
421  }
+
422  }
+
423  if (close_connection_)
+
424  {
+
425  adaptor_.shutdown_readwrite();
+
426  adaptor_.close();
+
427  CROW_LOG_DEBUG << this << " from write (static)";
+
428  }
+
429 
+
430  res.end();
+
431  res.clear();
+
432  buffers_.clear();
+
433  parser_.clear();
+
434  }
+
435 
+
436  void do_write_general()
+
437  {
+
438  if (res.body.length() < res_stream_threshold_)
+
439  {
+
440  res_body_copy_.swap(res.body);
+
441  buffers_.emplace_back(res_body_copy_.data(), res_body_copy_.size());
+
442 
+
443  do_write();
+
444 
+
445  if (need_to_start_read_after_complete_)
+
446  {
+
447  need_to_start_read_after_complete_ = false;
+
448  start_deadline();
+
449  do_read();
+
450  }
+
451  }
+
452  else
+
453  {
+
454  asio::write(adaptor_.socket(), buffers_); // Write the response start / headers
+
455  cancel_deadline_timer();
+
456  if (res.body.length() > 0)
+
457  {
+
458  std::vector<asio::const_buffer> buffers{1};
+
459  const uint8_t *data = reinterpret_cast<const uint8_t*>(res.body.data());
+
460  size_t length = res.body.length();
+
461  for(size_t transferred = 0; transferred < length;)
+
462  {
+
463  size_t to_transfer = CROW_MIN(16384UL, length-transferred);
+
464  buffers[0] = asio::const_buffer(data+transferred, to_transfer);
+
465  do_write_sync(buffers);
+
466  transferred += to_transfer;
+
467  }
+
468  }
+
469  if (close_connection_)
+
470  {
+
471  adaptor_.shutdown_readwrite();
+
472  adaptor_.close();
+
473  CROW_LOG_DEBUG << this << " from write (res_stream)";
+
474  }
+
475 
+
476  res.end();
+
477  res.clear();
+
478  buffers_.clear();
+
479  parser_.clear();
+
480  }
+
481  }
+
482 
+
483  void do_read()
+
484  {
+
485  auto self = this->shared_from_this();
+
486  adaptor_.socket().async_read_some(
+
487  asio::buffer(buffer_),
+
488  [self](const error_code& ec, std::size_t bytes_transferred) {
+
489  bool error_while_reading = true;
+
490  if (!ec)
+
491  {
+
492  bool ret = self->parser_.feed(self->buffer_.data(), bytes_transferred);
+
493  if (ret && self->adaptor_.is_open())
+
494  {
+
495  error_while_reading = false;
+
496  }
+
497  }
+
498 
+
499  if (error_while_reading)
+
500  {
+
501  self->cancel_deadline_timer();
+
502  self->parser_.done();
+
503  self->adaptor_.shutdown_read();
+
504  self->adaptor_.close();
+
505  CROW_LOG_DEBUG << self << " from read(1) with description: \"" << http_errno_description(static_cast<http_errno>(self->parser_.http_errno)) << '\"';
+
506  }
+
507  else if (self->close_connection_)
+
508  {
+
509  self->cancel_deadline_timer();
+
510  self->parser_.done();
+
511  // adaptor will close after write
+
512  }
+
513  else if (!self->need_to_call_after_handlers_)
+
514  {
+
515  self->start_deadline();
+
516  self->do_read();
+
517  }
+
518  else
+
519  {
+
520  // res will be completed later by user
+
521  self->need_to_start_read_after_complete_ = true;
+
522  }
+
523  });
+
524  }
+
525 
+
526  void do_write()
+
527  {
+
528  auto self = this->shared_from_this();
+
529  asio::async_write(
+
530  adaptor_.socket(), buffers_,
+
531  [self](const error_code& ec, std::size_t /*bytes_transferred*/) {
+
532  self->res.clear();
+
533  self->res_body_copy_.clear();
+
534  if (!self->continue_requested)
+
535  {
+
536  self->parser_.clear();
+
537  }
+
538  else
+
539  {
+
540  self->continue_requested = false;
+
541  }
+
542 
+
543  if (!ec)
+
544  {
+
545  if (self->close_connection_)
+
546  {
+
547  self->adaptor_.shutdown_write();
+
548  self->adaptor_.close();
+
549  CROW_LOG_DEBUG << self << " from write(1)";
+
550  }
+
551  }
+
552  else
+
553  {
+
554  CROW_LOG_DEBUG << self << " from write(2)";
+
555  }
+
556  });
+
557  }
+
558 
+
559  inline void do_write_sync(std::vector<asio::const_buffer>& buffers)
+
560  {
+
561 
+
562  asio::write(adaptor_.socket(), buffers, [&](error_code ec, std::size_t) {
+
563  if (!ec)
+
564  {
+
565  return false;
+
566  }
+
567  else
+
568  {
+
569  CROW_LOG_ERROR << ec << " - happened while sending buffers";
+
570  CROW_LOG_DEBUG << this << " from write (sync)(2)";
+
571  return true;
+
572  }
+
573  });
+
574  }
+
575 
+
576  void cancel_deadline_timer()
+
577  {
+
578  CROW_LOG_DEBUG << this << " timer cancelled: " << &task_timer_ << ' ' << task_id_;
+
579  task_timer_.cancel(task_id_);
+
580  }
+
581 
+
582  void start_deadline(/*int timeout = 5*/)
+
583  {
+
584  cancel_deadline_timer();
+
585 
+
586  auto self = this->shared_from_this();
+
587  task_id_ = task_timer_.schedule([self] {
+
588  if (!self->adaptor_.is_open())
+
589  {
+
590  return;
+
591  }
+
592  self->adaptor_.shutdown_readwrite();
+
593  self->adaptor_.close();
+
594  });
+
595  CROW_LOG_DEBUG << this << " timer added: " << &task_timer_ << ' ' << task_id_;
+
596  }
+
597 
+
598  private:
+
599  Adaptor adaptor_;
+
600  Handler* handler_;
+
601 
+
602  std::array<char, 4096> buffer_;
+
603 
+
604  HTTPParser<Connection> parser_;
+
605  std::unique_ptr<routing_handle_result> routing_handle_result_;
+
606  request& req_;
+
607  response res;
+
608 
+
609  bool close_connection_ = false;
+
610 
+
611  const std::string& server_name_;
+
612  std::vector<asio::const_buffer> buffers_;
+
613 
+
614  std::string content_length_;
+
615  std::string date_str_;
+
616  std::string res_body_copy_;
+
617 
+
618  detail::task_timer::identifier_type task_id_{};
+
619 
+
620  bool continue_requested{};
+
621  bool need_to_call_after_handlers_{};
+
622  bool need_to_start_read_after_complete_{};
+
623  bool add_keep_alive_{};
+
624 
+
625  std::tuple<Middlewares...>* middlewares_;
+
626  detail::context<Middlewares...> ctx_;
+
627 
+
628  std::function<std::string()>& get_cached_date_str;
+
629  detail::task_timer& task_timer_;
+
630 
+
631  size_t res_stream_threshold_;
+
632 
+
633  std::atomic<unsigned int>& queue_length_;
+
634  };
+
635 
+
636 } // namespace crow
+
An HTTP connection.
Definition: http_connection.h:48
+
void complete_request()
Call the after handle middleware and send the write the response to the connection.
Definition: http_connection.h:218
+
decltype(std::declval< Adaptor >().raw_socket()) & socket()
The TCP socket on top of which the connection is established.
Definition: http_connection.h:87
+
A class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 ...
Definition: task_timer.h:34
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
const std::string & get_header_value(const T &headers, const std::string &key)
Find and return the value associated with the key. (returns an empty string if nothing is found)
Definition: http_request.h:24
+ +
bool close_connection
Whether or not the server should shut down the TCP connection once a response is sent.
Definition: http_request.h:46
+
bool keep_alive
Whether or not the server should send a connection: Keep-Alive header to the client.
Definition: http_request.h:45
+
std::string url
The endpoint without any parameters.
Definition: http_request.h:39
+
std::string remote_ip_address
The IP address from which the request was sent.
Definition: http_request.h:43
+
bool upgrade
Whether or noth the server should change the HTTP connection to a different connection.
Definition: http_request.h:47
+
HTTP response.
Definition: http_response.h:34
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/http__parser__merged_8h_source.html b/1.2/reference/http__parser__merged_8h_source.html new file mode 100644 index 000000000..28114eb67 --- /dev/null +++ b/1.2/reference/http__parser__merged_8h_source.html @@ -0,0 +1,2138 @@ + + + + + + + + Crow: include/crow/http_parser_merged.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
http_parser_merged.h
+
+
+
1 /* merged revision: 5b951d74bd66ec9d38448e0a85b1cf8b85d97db3 */
+
2 /* updated to : e13b274770da9b82a1085dec29182acfea72e7a7 (beyond v2.9.5) */
+
3 /* commits not included:
+
4  * 091ebb87783a58b249062540bbea07de2a11e9cf
+
5  * 6132d1fefa03f769a3979355d1f5da0b8889cad2
+
6  * 7ba312397c2a6c851a4b5efe6c1603b1e1bda6ff
+
7  * d7675453a6c03180572f084e95eea0d02df39164
+
8  * dff604db203986e532e5a679bafd0e7382c6bdd9 (Might be useful to actually add [upgrade requests with a body])
+
9  * e01811e7f4894d7f0f7f4bd8492cccec6f6b4038 (related to above)
+
10  * 05525c5fde1fc562481f6ae08fa7056185325daf (also related to above)
+
11  * 350258965909f249f9c59823aac240313e0d0120 (cannot be implemented due to upgrade)
+
12  */
+
13 
+
14 // clang-format off
+
15 #pragma once
+
16 extern "C" {
+
17 #include <stddef.h>
+
18 #if defined(_WIN32) && !defined(__MINGW32__) && \
+
19  (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
+
20 #include <BaseTsd.h>
+
21 typedef __int8 int8_t;
+
22 typedef unsigned __int8 uint8_t;
+
23 typedef __int16 int16_t;
+
24 typedef unsigned __int16 uint16_t;
+
25 typedef __int32 int32_t;
+
26 typedef unsigned __int32 uint32_t;
+
27 typedef __int64 int64_t;
+
28 typedef unsigned __int64 uint64_t;
+
29 #elif (defined(__sun) || defined(__sun__)) && defined(__SunOS_5_9)
+
30 #include <sys/inttypes.h>
+
31 #else
+
32 #include <stdint.h>
+
33 #endif
+
34 #include <assert.h>
+
35 #include <ctype.h>
+
36 #include <string.h>
+
37 #include <limits.h>
+
38 }
+
39 
+
40 #include "crow/common.h"
+
41 namespace crow
+
42 {
+
43 /* Maximium header size allowed. If the macro is not defined
+
44  * before including this header then the default is used. To
+
45  * change the maximum header size, define the macro in the build
+
46  * environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
+
47  * the effective limit on the size of the header, define the macro
+
48  * to a very large number (e.g. -DCROW_HTTP_MAX_HEADER_SIZE=0x7fffffff)
+
49  */
+
50 #ifndef CROW_HTTP_MAX_HEADER_SIZE
+
51 # define CROW_HTTP_MAX_HEADER_SIZE (80*1024)
+
52 #endif
+
53 
+
54 typedef struct http_parser http_parser;
+
55 typedef struct http_parser_settings http_parser_settings;
+
56 
+
57 /* Callbacks should return non-zero to indicate an error. The parser will
+
58  * then halt execution.
+
59  *
+
60  * The one exception is on_headers_complete. In a HTTP_RESPONSE parser
+
61  * returning '1' from on_headers_complete will tell the parser that it
+
62  * should not expect a body. This is used when receiving a response to a
+
63  * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
+
64  * chunked' headers that indicate the presence of a body.
+
65  *
+
66  * Returning `2` from on_headers_complete will tell parser that it should not
+
67  * expect neither a body nor any futher responses on this connection. This is
+
68  * useful for handling responses to a CONNECT request which may not contain
+
69  * `Upgrade` or `Connection: upgrade` headers.
+
70  *
+
71  * http_data_cb does not return data chunks. It will be called arbitrarally
+
72  * many times for each string. E.G. you might get 10 callbacks for "on_url"
+
73  * each providing just a few characters more data.
+
74  */
+
75 typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
+
76 typedef int (*http_cb) (http_parser*);
+
77 
+
78 
+
79 /* Flag values for http_parser.flags field */
+
80 enum http_connection_flags // This is basically 7 booleans placed into 1 integer. Uses 4 bytes instead of n bytes (7 currently).
+
81  { F_CHUNKED = 1 << 0 // 00000000 00000000 00000000 00000001
+
82  , F_CONNECTION_KEEP_ALIVE = 1 << 1 // 00000000 00000000 00000000 00000010
+
83  , F_CONNECTION_CLOSE = 1 << 2 // 00000000 00000000 00000000 00000100
+
84  , F_TRAILING = 1 << 3 // 00000000 00000000 00000000 00001000
+
85  , F_UPGRADE = 1 << 4 // 00000000 00000000 00000000 00010000
+
86  , F_SKIPBODY = 1 << 5 // 00000000 00000000 00000000 00100000
+
87  , F_CONTENTLENGTH = 1 << 6 // 00000000 00000000 00000000 01000000
+
88  };
+
89 
+
90 
+
91 /* Map for errno-related constants
+
92  *
+
93  * The provided argument should be a macro that takes 2 arguments.
+
94  */
+
95 #define CROW_HTTP_ERRNO_MAP(CROW_XX) \
+
96  /* No error */ \
+
97  CROW_XX(OK, "success") \
+
98  \
+
99  /* Callback-related errors */ \
+
100  CROW_XX(CB_message_begin, "the on_message_begin callback failed") \
+
101  CROW_XX(CB_method, "the on_method callback failed") \
+
102  CROW_XX(CB_url, "the \"on_url\" callback failed") \
+
103  CROW_XX(CB_header_field, "the \"on_header_field\" callback failed") \
+
104  CROW_XX(CB_header_value, "the \"on_header_value\" callback failed") \
+
105  CROW_XX(CB_headers_complete, "the \"on_headers_complete\" callback failed") \
+
106  CROW_XX(CB_body, "the \"on_body\" callback failed") \
+
107  CROW_XX(CB_message_complete, "the \"on_message_complete\" callback failed") \
+
108  CROW_XX(CB_status, "the \"on_status\" callback failed") \
+
109  \
+
110  /* Parsing-related errors */ \
+
111  CROW_XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
+
112  CROW_XX(HEADER_OVERFLOW, "too many header bytes seen; overflow detected") \
+
113  CROW_XX(CLOSED_CONNECTION, "data received after completed connection: close message") \
+
114  CROW_XX(INVALID_VERSION, "invalid HTTP version") \
+
115  CROW_XX(INVALID_STATUS, "invalid HTTP status code") \
+
116  CROW_XX(INVALID_METHOD, "invalid HTTP method") \
+
117  CROW_XX(INVALID_URL, "invalid URL") \
+
118  CROW_XX(INVALID_HOST, "invalid host") \
+
119  CROW_XX(INVALID_PORT, "invalid port") \
+
120  CROW_XX(INVALID_PATH, "invalid path") \
+
121  CROW_XX(INVALID_QUERY_STRING, "invalid query string") \
+
122  CROW_XX(INVALID_FRAGMENT, "invalid fragment") \
+
123  CROW_XX(LF_EXPECTED, "LF character expected") \
+
124  CROW_XX(INVALID_HEADER_TOKEN, "invalid character in header") \
+
125  CROW_XX(INVALID_CONTENT_LENGTH, "invalid character in content-length header") \
+
126  CROW_XX(UNEXPECTED_CONTENT_LENGTH, "unexpected content-length header") \
+
127  CROW_XX(INVALID_CHUNK_SIZE, "invalid character in chunk size header") \
+
128  CROW_XX(INVALID_CONSTANT, "invalid constant string") \
+
129  CROW_XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state") \
+
130  CROW_XX(STRICT, "strict mode assertion failed") \
+
131  CROW_XX(UNKNOWN, "an unknown error occurred") \
+
132  CROW_XX(INVALID_TRANSFER_ENCODING, "request has invalid transfer-encoding") \
+
133 
+
134 
+
135 /* Define CHPE_* values for each errno value above */
+
136 #define CROW_HTTP_ERRNO_GEN(n, s) CHPE_##n,
+
137 enum http_errno {
+
138  CROW_HTTP_ERRNO_MAP(CROW_HTTP_ERRNO_GEN)
+
139 };
+
140 #undef CROW_HTTP_ERRNO_GEN
+
141 
+
142 
+
143 /* Get an http_errno value from an http_parser */
+
144 #define CROW_HTTP_PARSER_ERRNO(p) ((enum http_errno)(p)->http_errno)
+
145 
+
146 
+
147  struct http_parser
+
148  {
+
149  /** PRIVATE **/
+
150  unsigned int flags : 7; /* F_* values from 'flags' enum; semi-public */
+
151  unsigned int state : 8; /* enum state from http_parser.c */
+
152  unsigned int header_state : 7; /* enum header_state from http_parser.c */
+
153  unsigned int index : 5; /* index into current matcher */
+
154  unsigned int uses_transfer_encoding : 1; /* Transfer-Encoding header is present */
+
155  unsigned int allow_chunked_length : 1; /* Allow headers with both `Content-Length` and `Transfer-Encoding: chunked` set */
+
156  unsigned int lenient_http_headers : 1;
+
157 
+
158  uint32_t nread; /* # bytes read in various scenarios */
+
159  uint64_t content_length; /* # bytes in body. `(uint64_t) -1` (all bits one) if no Content-Length header. */
+
160  unsigned long qs_point;
+
161 
+
162  /** READ-ONLY **/
+
163  unsigned char http_major;
+
164  unsigned char http_minor;
+
165  unsigned int method : 8; /* requests only */
+
166  unsigned int http_errno : 7;
+
167 
+
168  /* 1 = Upgrade header was present and the parser has exited because of that.
+
169  * 0 = No upgrade header present.
+
170  * Should be checked when http_parser_execute() returns in addition to
+
171  * error checking.
+
172  */
+
173  unsigned int upgrade : 1;
+
174 
+
175  /** PUBLIC **/
+
176  void* data; /* A pointer to get hook to the "connection" or "socket" object */
+
177  };
+
178 
+
179 
+ +
181  {
+
182  http_cb on_message_begin;
+
183  http_cb on_method;
+
184  http_data_cb on_url;
+
185  http_data_cb on_header_field;
+
186  http_data_cb on_header_value;
+
187  http_cb on_headers_complete;
+
188  http_data_cb on_body;
+
189  http_cb on_message_complete;
+
190  };
+
191 
+
192 
+
193 
+
194 // SOURCE (.c) CODE
+
195 static uint32_t max_header_size = CROW_HTTP_MAX_HEADER_SIZE;
+
196 
+
197 #ifndef CROW_ULLONG_MAX
+
198 # define CROW_ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
+
199 #endif
+
200 
+
201 #ifndef CROW_MIN
+
202 # define CROW_MIN(a,b) ((a) < (b) ? (a) : (b))
+
203 #endif
+
204 
+
205 #ifndef CROW_ARRAY_SIZE
+
206 # define CROW_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
207 #endif
+
208 
+
209 #ifndef CROW_BIT_AT
+
210 # define CROW_BIT_AT(a, i) \
+
211  (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \
+
212  (1 << ((unsigned int) (i) & 7))))
+
213 #endif
+
214 
+
215 #define CROW_SET_ERRNO(e) \
+
216 do { \
+
217  parser->nread = nread; \
+
218  parser->http_errno = (e); \
+
219 } while(0)
+
220 
+
221 /* Run the notify callback FOR, returning ER if it fails */
+
222 #define CROW_CALLBACK_NOTIFY_(FOR, ER) \
+
223 do { \
+
224  assert(CROW_HTTP_PARSER_ERRNO(parser) == CHPE_OK); \
+
225  \
+
226  if (CROW_LIKELY(settings->on_##FOR)) { \
+
227  if (CROW_UNLIKELY(0 != settings->on_##FOR(parser))) { \
+
228  CROW_SET_ERRNO(CHPE_CB_##FOR); \
+
229  } \
+
230  \
+
231  /* We either errored above or got paused; get out */ \
+
232  if (CROW_UNLIKELY(CROW_HTTP_PARSER_ERRNO(parser) != CHPE_OK)) { \
+
233  return (ER); \
+
234  } \
+
235  } \
+
236 } while (0)
+
237 
+
238 /* Run the notify callback FOR and consume the current byte */
+
239 #define CROW_CALLBACK_NOTIFY(FOR) CROW_CALLBACK_NOTIFY_(FOR, p - data + 1)
+
240 
+
241 /* Run the notify callback FOR and don't consume the current byte */
+
242 #define CROW_CALLBACK_NOTIFY_NOADVANCE(FOR) CROW_CALLBACK_NOTIFY_(FOR, p - data)
+
243 
+
244 /* Run data callback FOR with LEN bytes, returning ER if it fails */
+
245 #define CROW_CALLBACK_DATA_(FOR, LEN, ER) \
+
246 do { \
+
247  assert(CROW_HTTP_PARSER_ERRNO(parser) == CHPE_OK); \
+
248  \
+
249  if (FOR##_mark) { \
+
250  if (CROW_LIKELY(settings->on_##FOR)) { \
+
251  if (CROW_UNLIKELY(0 != \
+
252  settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \
+
253  CROW_SET_ERRNO(CHPE_CB_##FOR); \
+
254  } \
+
255  \
+
256  /* We either errored above or got paused; get out */ \
+
257  if (CROW_UNLIKELY(CROW_HTTP_PARSER_ERRNO(parser) != CHPE_OK)) {\
+
258  return (ER); \
+
259  } \
+
260  } \
+
261  FOR##_mark = NULL; \
+
262  } \
+
263 } while (0)
+
264 
+
265 /* Run the data callback FOR and consume the current byte */
+
266 #define CROW_CALLBACK_DATA(FOR) \
+
267  CROW_CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
+
268 
+
269 /* Run the data callback FOR and don't consume the current byte */
+
270 #define CROW_CALLBACK_DATA_NOADVANCE(FOR) \
+
271  CROW_CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
+
272 
+
273 /* Set the mark FOR; non-destructive if mark is already set */
+
274 #define CROW_MARK(FOR) \
+
275 do { \
+
276  if (!FOR##_mark) { \
+
277  FOR##_mark = p; \
+
278  } \
+
279 } while (0)
+
280 
+
281 /* Don't allow the total size of the HTTP headers (including the status
+
282  * line) to exceed max_header_size. This check is here to protect
+
283  * embedders against denial-of-service attacks where the attacker feeds
+
284  * us a never-ending header that the embedder keeps buffering.
+
285  *
+
286  * This check is arguably the responsibility of embedders but we're doing
+
287  * it on the embedder's behalf because most won't bother and this way we
+
288  * make the web a little safer. max_header_size is still far bigger
+
289  * than any reasonable request or response so this should never affect
+
290  * day-to-day operation.
+
291  */
+
292 #define CROW_COUNT_HEADER_SIZE(V) \
+
293 do { \
+
294  nread += (uint32_t)(V); \
+
295  if (CROW_UNLIKELY(nread > max_header_size)) { \
+
296  CROW_SET_ERRNO(CHPE_HEADER_OVERFLOW); \
+
297  goto error; \
+
298  } \
+
299 } while (0)
+
300 #define CROW_REEXECUTE() \
+
301  goto reexecute; \
+
302 
+
303 #define CROW_PROXY_CONNECTION "proxy-connection"
+
304 #define CROW_CONNECTION "connection"
+
305 #define CROW_CONTENT_LENGTH "content-length"
+
306 #define CROW_TRANSFER_ENCODING "transfer-encoding"
+
307 #define CROW_UPGRADE "upgrade"
+
308 #define CROW_CHUNKED "chunked"
+
309 #define CROW_KEEP_ALIVE "keep-alive"
+
310 #define CROW_CLOSE "close"
+
311 
+
312 
+
313 
+
314  enum state
+
315  {
+
316  s_dead = 1 /* important that this is > 0 */
+
317 
+
318  ,
+
319  s_start_req
+
320 
+
321  ,
+
322  s_req_method,
+
323  s_req_spaces_before_url,
+
324  s_req_schema,
+
325  s_req_schema_slash,
+
326  s_req_schema_slash_slash,
+
327  s_req_server_start,
+
328  s_req_server, // }
+
329  s_req_server_with_at, // |
+
330  s_req_path, // | The parser recognizes how to switch between these states,
+
331  s_req_query_string_start, // | however it doesn't process them any differently.
+
332  s_req_query_string, // }
+
333  s_req_http_start,
+
334  s_req_http_H,
+
335  s_req_http_HT,
+
336  s_req_http_HTT,
+
337  s_req_http_HTTP,
+
338  s_req_http_I,
+
339  s_req_http_IC,
+
340  s_req_http_major,
+
341  s_req_http_dot,
+
342  s_req_http_minor,
+
343  s_req_http_end,
+
344  s_req_line_almost_done
+
345 
+
346  ,
+
347  s_header_field_start,
+
348  s_header_field,
+
349  s_header_value_discard_ws,
+
350  s_header_value_discard_ws_almost_done,
+
351  s_header_value_discard_lws,
+
352  s_header_value_start,
+
353  s_header_value,
+
354  s_header_value_lws
+
355 
+
356  ,
+
357  s_header_almost_done
+
358 
+
359  ,
+
360  s_chunk_size_start,
+
361  s_chunk_size,
+
362  s_chunk_parameters,
+
363  s_chunk_size_almost_done
+
364 
+
365  ,
+
366  s_headers_almost_done,
+
367  s_headers_done
+
368 
+
369  /* Important: 's_headers_done' must be the last 'header' state. All
+
370  * states beyond this must be 'body' states. It is used for overflow
+
371  * checking. See the CROW_PARSING_HEADER() macro.
+
372  */
+
373 
+
374  ,
+
375  s_chunk_data,
+
376  s_chunk_data_almost_done,
+
377  s_chunk_data_done
+
378 
+
379  ,
+
380  s_body_identity,
+
381  s_body_identity_eof
+
382 
+
383  ,
+
384  s_message_done
+
385  };
+
386 
+
387 
+
388 #define CROW_PARSING_HEADER(state) (state <= s_headers_done)
+
389 
+
390 
+
391 enum header_states
+
392  { h_general = 0
+
393  , h_C
+
394  , h_CO
+
395  , h_CON
+
396 
+
397  , h_matching_connection
+
398  , h_matching_proxy_connection
+
399  , h_matching_content_length
+
400  , h_matching_transfer_encoding
+
401  , h_matching_upgrade
+
402 
+
403  , h_connection
+
404  , h_content_length
+
405  , h_content_length_num
+
406  , h_content_length_ws
+
407  , h_transfer_encoding
+
408  , h_upgrade
+
409 
+
410  , h_matching_transfer_encoding_token_start
+
411  , h_matching_transfer_encoding_chunked
+
412  , h_matching_transfer_encoding_token
+
413 
+
414  , h_matching_connection_keep_alive
+
415  , h_matching_connection_close
+
416 
+
417  , h_transfer_encoding_chunked
+
418  , h_connection_keep_alive
+
419  , h_connection_close
+
420  };
+
421 
+
422 enum http_host_state
+
423  {
+
424  s_http_host_dead = 1
+
425  , s_http_userinfo_start
+
426  , s_http_userinfo
+
427  , s_http_host_start
+
428  , s_http_host_v6_start
+
429  , s_http_host
+
430  , s_http_host_v6
+
431  , s_http_host_v6_end
+
432  , s_http_host_v6_zone_start
+
433  , s_http_host_v6_zone
+
434  , s_http_host_port_start
+
435  , s_http_host_port
+
436 };
+
437 
+
438 /* Macros for character classes; depends on strict-mode */
+
439 #define CROW_LOWER(c) (unsigned char)(c | 0x20)
+
440 #define CROW_IS_ALPHA(c) (CROW_LOWER(c) >= 'a' && CROW_LOWER(c) <= 'z')
+
441 #define CROW_IS_NUM(c) ((c) >= '0' && (c) <= '9')
+
442 #define CROW_IS_ALPHANUM(c) (CROW_IS_ALPHA(c) || CROW_IS_NUM(c))
+
443 //#define CROW_IS_HEX(c) (CROW_IS_NUM(c) || (CROW_LOWER(c) >= 'a' && CROW_LOWER(c) <= 'f'))
+
444 #define CROW_IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \
+
445  (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
+
446  (c) == ')')
+
447 #define CROW_IS_USERINFO_CHAR(c) (CROW_IS_ALPHANUM(c) || CROW_IS_MARK(c) || (c) == '%' || \
+
448  (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
+
449  (c) == '$' || (c) == ',')
+
450 
+
451 #define CROW_TOKEN(c) (tokens[(unsigned char)c])
+
452 #define CROW_IS_URL_CHAR(c) (CROW_BIT_AT(normal_url_char, (unsigned char)c))
+
453 //#define CROW_IS_HOST_CHAR(c) (CROW_IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
+
454 
+
455  /**
+
456  * Verify that a char is a valid visible (printable) US-ASCII
+
457  * character or %x80-FF
+
458  **/
+
459 #define CROW_IS_HEADER_CHAR(ch) \
+
460  (ch == cr || ch == lf || ch == 9 || ((unsigned char)ch > 31 && ch != 127))
+
461 
+
462 #define CROW_start_state s_start_req
+
463 
+
464 # define CROW_STRICT_CHECK(cond) \
+
465 do { \
+
466  if (cond) { \
+
467  CROW_SET_ERRNO(CHPE_STRICT); \
+
468  goto error; \
+
469  } \
+
470 } while (0)
+
471 #define CROW_NEW_MESSAGE() (CROW_start_state)
+
472 
+
473 /* Our URL parser.
+
474  *
+
475  * This is designed to be shared by http_parser_execute() for URL validation,
+
476  * hence it has a state transition + byte-for-byte interface. In addition, it
+
477  * is meant to be embedded in http_parser_parse_url(), which does the dirty
+
478  * work of turning state transitions URL components for its API.
+
479  *
+
480  * This function should only be invoked with non-space characters. It is
+
481  * assumed that the caller cares about (and can detect) the transition between
+
482  * URL and non-URL states by looking for these.
+
483  */
+
484 inline enum state
+
485 parse_url_char(enum state s, const char ch, http_parser *parser, const char* url_mark, const char* p)
+
486 {
+
487 # define CROW_T(v) 0
+
488 
+
489 
+
490 static const uint8_t normal_url_char[32] = {
+
491 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
+
492  0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
+
493 /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
+
494  0 |CROW_T(2)| 0 | 0 |CROW_T(16)| 0 | 0 | 0,
+
495 /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
+
496  0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
+
497 /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
+
498  0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
+
499 /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
+
500  0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
+
501 /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
+
502  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+
503 /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
+
504  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+
505 /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
+
506  1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
+
507 /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
+
508  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+
509 /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
+
510  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+
511 /* 80 P 81 Q 82 R 83 S 84 CROW_T 85 U 86 V 87 W */
+
512  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+
513 /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
+
514  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+
515 /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
+
516  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+
517 /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
+
518  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+
519 /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
+
520  1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
+
521 /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
+
522  1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, };
+
523 
+
524 #undef CROW_T
+
525 
+
526  if (ch == ' ' || ch == '\r' || ch == '\n') {
+
527  return s_dead;
+
528  }
+
529  if (ch == '\t' || ch == '\f') {
+
530  return s_dead;
+
531  }
+
532 
+
533  switch (s) {
+
534  case s_req_spaces_before_url:
+
535  /* Proxied requests are followed by scheme of an absolute URI (alpha).
+
536  * All methods except CONNECT are followed by '/' or '*'.
+
537  */
+
538 
+
539  if (ch == '/' || ch == '*') {
+
540  return s_req_path;
+
541  }
+
542 
+
543  if (CROW_IS_ALPHA(ch)) {
+
544  return s_req_schema;
+
545  }
+
546 
+
547  break;
+
548 
+
549  case s_req_schema:
+
550  if (CROW_IS_ALPHA(ch)) {
+
551  return s;
+
552  }
+
553 
+
554  if (ch == ':') {
+
555  return s_req_schema_slash;
+
556  }
+
557 
+
558  break;
+
559 
+
560  case s_req_schema_slash:
+
561  if (ch == '/') {
+
562  return s_req_schema_slash_slash;
+
563  }
+
564 
+
565  break;
+
566 
+
567  case s_req_schema_slash_slash:
+
568  if (ch == '/') {
+
569  return s_req_server_start;
+
570  }
+
571 
+
572  break;
+
573 
+
574  case s_req_server_with_at:
+
575  if (ch == '@') {
+
576  return s_dead;
+
577  }
+
578 
+
579  /* fall through */
+
580  case s_req_server_start:
+
581  case s_req_server:
+
582  if (ch == '/') {
+
583  return s_req_path;
+
584  }
+
585 
+
586  if (ch == '?') {
+
587  parser->qs_point = p - url_mark;
+
588  return s_req_query_string_start;
+
589  }
+
590 
+
591  if (ch == '@') {
+
592  return s_req_server_with_at;
+
593  }
+
594 
+
595  if (CROW_IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
+
596  return s_req_server;
+
597  }
+
598 
+
599  break;
+
600 
+
601  case s_req_path:
+
602  if (CROW_IS_URL_CHAR(ch)) {
+
603  return s;
+
604  }
+
605  else if (ch == '?')
+
606  {
+
607  parser->qs_point = p - url_mark;
+
608  return s_req_query_string_start;
+
609  }
+
610 
+
611  break;
+
612 
+
613  case s_req_query_string_start:
+
614  case s_req_query_string:
+
615  if (CROW_IS_URL_CHAR(ch)) {
+
616  return s_req_query_string;
+
617  }
+
618  else if (ch == '?')
+
619  {
+
620  return s_req_query_string;
+
621  }
+
622 
+
623  break;
+
624 
+
625  default:
+
626  break;
+
627  }
+
628 
+
629  /* We should never fall out of the switch above unless there's an error */
+
630  return s_dead;
+
631 }
+
632 
+
633 inline size_t http_parser_execute (http_parser *parser,
+
634  const http_parser_settings *settings,
+
635  const char *data,
+
636  size_t len)
+
637 {
+
638 
+
639 /* Tokens as defined by rfc 2616. Also lowercases them.
+
640  * token = 1*<any CHAR except CTLs or separators>
+
641  * separators = "(" | ")" | "<" | ">" | "@"
+
642  * | "," | ";" | ":" | "\" | <">
+
643  * | "/" | "[" | "]" | "?" | "="
+
644  * | "{" | "}" | SP | HT
+
645  */
+
646 static const char tokens[256] = {
+
647 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
+
648  0, 0, 0, 0, 0, 0, 0, 0,
+
649 /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
+
650  0, 0, 0, 0, 0, 0, 0, 0,
+
651 /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
+
652  0, 0, 0, 0, 0, 0, 0, 0,
+
653 /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
+
654  0, 0, 0, 0, 0, 0, 0, 0,
+
655 /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
+
656  0, '!', 0, '#', '$', '%', '&', '\'',
+
657 /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
+
658  0, 0, '*', '+', 0, '-', '.', 0,
+
659 /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
+
660  '0', '1', '2', '3', '4', '5', '6', '7',
+
661 /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
+
662  '8', '9', 0, 0, 0, 0, 0, 0,
+
663 /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
+
664  0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+
665 /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
+
666  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+
667 /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
+
668  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+
669 /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
+
670  'x', 'y', 'z', 0, 0, 0, '^', '_',
+
671 /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
+
672  '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+
673 /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
+
674  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+
675 /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
+
676  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+
677 /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
+
678  'x', 'y', 'z', 0, '|', 0, '~', 0 };
+
679 
+
680 
+
681 static const int8_t unhex[256] =
+
682  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+
683  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+
684  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+
685  , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
+
686  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+
687  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+
688  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
+
689  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
+
690  };
+
691 
+
692 
+
693 
+
694  char c, ch;
+
695  int8_t unhex_val;
+
696  const char *p = data;
+
697  const char *header_field_mark = 0;
+
698  const char *header_value_mark = 0;
+
699  const char *url_mark = 0;
+
700  const char *url_start_mark = 0;
+
701  const char *body_mark = 0;
+
702  const unsigned int lenient = parser->lenient_http_headers;
+
703  const unsigned int allow_chunked_length = parser->allow_chunked_length;
+
704 
+
705  uint32_t nread = parser->nread;
+
706 
+
707  /* We're in an error state. Don't bother doing anything. */
+
708  if (CROW_HTTP_PARSER_ERRNO(parser) != CHPE_OK) {
+
709  return 0;
+
710  }
+
711 
+
712  if (len == 0) {
+
713  switch (parser->state) {
+
714  case s_body_identity_eof:
+
715  /* Use of CROW_CALLBACK_NOTIFY() here would erroneously return 1 byte read if we got paused. */
+
716  CROW_CALLBACK_NOTIFY_NOADVANCE(message_complete);
+
717  return 0;
+
718 
+
719  case s_dead:
+
720  case s_start_req:
+
721  return 0;
+
722 
+
723  default:
+
724  CROW_SET_ERRNO(CHPE_INVALID_EOF_STATE);
+
725  return 1;
+
726  }
+
727  }
+
728 
+
729 
+
730  if (parser->state == s_header_field)
+
731  header_field_mark = data;
+
732  if (parser->state == s_header_value)
+
733  header_value_mark = data;
+
734  switch (parser->state) {
+
735  case s_req_path:
+
736  case s_req_schema:
+
737  case s_req_schema_slash:
+
738  case s_req_schema_slash_slash:
+
739  case s_req_server_start:
+
740  case s_req_server:
+
741  case s_req_server_with_at:
+
742  case s_req_query_string_start:
+
743  case s_req_query_string:
+
744  url_mark = data;
+
745  break;
+
746  default:
+
747  break;
+
748  }
+
749 
+
750  for (p=data; p != data + len; p++) {
+
751  ch = *p;
+
752 
+
753  if (CROW_PARSING_HEADER(parser->state))
+
754  CROW_COUNT_HEADER_SIZE(1);
+
755 
+
756 reexecute:
+
757  switch (parser->state) {
+
758 
+
759  case s_dead:
+
760  /* this state is used after a 'Connection: close' message
+
761  * the parser will error out if it reads another message
+
762  */
+
763  if (CROW_LIKELY(ch == cr || ch == lf))
+
764  break;
+
765 
+
766  CROW_SET_ERRNO(CHPE_CLOSED_CONNECTION);
+
767  goto error;
+
768 
+
769  case s_start_req:
+
770  {
+
771  if (ch == cr || ch == lf)
+
772  break;
+
773  parser->flags = 0;
+
774  parser->uses_transfer_encoding = 0;
+
775  parser->content_length = CROW_ULLONG_MAX;
+
776 
+
777  if (CROW_UNLIKELY(!CROW_IS_ALPHA(ch))) {
+
778  CROW_SET_ERRNO(CHPE_INVALID_METHOD);
+
779  goto error;
+
780  }
+
781 
+
782  parser->method = 0;
+
783  parser->index = 1;
+
784  switch (ch) {
+
785  case 'A': parser->method = (unsigned)HTTPMethod::Acl; break;
+
786  case 'B': parser->method = (unsigned)HTTPMethod::Bind; break;
+
787  case 'C': parser->method = (unsigned)HTTPMethod::Connect; /* or COPY, CHECKOUT */ break;
+
788  case 'D': parser->method = (unsigned)HTTPMethod::Delete; break;
+
789  case 'G': parser->method = (unsigned)HTTPMethod::Get; break;
+
790  case 'H': parser->method = (unsigned)HTTPMethod::Head; break;
+
791  case 'L': parser->method = (unsigned)HTTPMethod::Lock; /* or LINK */ break;
+
792  case 'M': parser->method = (unsigned)HTTPMethod::MkCol; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
+
793  case 'N': parser->method = (unsigned)HTTPMethod::Notify; break;
+
794  case 'O': parser->method = (unsigned)HTTPMethod::Options; break;
+
795  case 'P': parser->method = (unsigned)HTTPMethod::Post; /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ break;
+
796  case 'R': parser->method = (unsigned)HTTPMethod::Report; /* or REBIND */ break;
+
797  case 'S': parser->method = (unsigned)HTTPMethod::Subscribe; /* or SEARCH, SOURCE */ break;
+
798  case 'T': parser->method = (unsigned)HTTPMethod::Trace; break;
+
799  case 'U': parser->method = (unsigned)HTTPMethod::Unlock; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
+
800  default:
+
801  CROW_SET_ERRNO(CHPE_INVALID_METHOD);
+
802  goto error;
+
803  }
+
804  parser->state = s_req_method;
+
805 
+
806  CROW_CALLBACK_NOTIFY(message_begin);
+
807 
+
808  break;
+
809  }
+
810 
+
811  case s_req_method:
+
812  {
+
813  const char *matcher;
+
814  if (CROW_UNLIKELY(ch == '\0')) {
+
815  CROW_SET_ERRNO(CHPE_INVALID_METHOD);
+
816  goto error;
+
817  }
+
818 
+
819  matcher = method_strings[parser->method];
+
820  if (ch == ' ' && matcher[parser->index] == '\0') {
+
821  parser->state = s_req_spaces_before_url;
+
822  } else if (ch == matcher[parser->index]) {
+
823  ; /* nada */
+
824  } else if ((ch >= 'A' && ch <= 'Z') || ch == '-') {
+
825 
+
826  switch (parser->method << 16 | parser->index << 8 | ch) {
+
827 #define CROW_XX(meth, pos, ch, new_meth) \
+
828  case ((unsigned)HTTPMethod::meth << 16 | pos << 8 | ch): \
+
829  parser->method = (unsigned)HTTPMethod::new_meth; break;
+
830 
+
831  CROW_XX(Post, 1, 'U', Put)
+
832  CROW_XX(Post, 1, 'A', Patch)
+
833  CROW_XX(Post, 1, 'R', Propfind)
+
834  CROW_XX(Put, 2, 'R', Purge)
+
835  CROW_XX(Connect, 1, 'H', Checkout)
+
836  CROW_XX(Connect, 2, 'P', Copy)
+
837  CROW_XX(MkCol, 1, 'O', Move)
+
838  CROW_XX(MkCol, 1, 'E', Merge)
+
839  CROW_XX(MkCol, 1, '-', MSearch)
+
840  CROW_XX(MkCol, 2, 'A', MkActivity)
+
841  CROW_XX(MkCol, 3, 'A', MkCalendar)
+
842  CROW_XX(Subscribe, 1, 'E', Search)
+
843  CROW_XX(Subscribe, 1, 'O', Source)
+
844  CROW_XX(Report, 2, 'B', Rebind)
+
845  CROW_XX(Propfind, 4, 'P', Proppatch)
+
846  CROW_XX(Lock, 1, 'I', Link)
+
847  CROW_XX(Unlock, 2, 'S', Unsubscribe)
+
848  CROW_XX(Unlock, 2, 'B', Unbind)
+
849  CROW_XX(Unlock, 3, 'I', Unlink)
+
850 #undef CROW_XX
+
851  default:
+
852  CROW_SET_ERRNO(CHPE_INVALID_METHOD);
+
853  goto error;
+
854  }
+
855  } else {
+
856  CROW_SET_ERRNO(CHPE_INVALID_METHOD);
+
857  goto error;
+
858  }
+
859 
+
860  CROW_CALLBACK_NOTIFY_NOADVANCE(method);
+
861 
+
862  ++parser->index;
+
863  break;
+
864  }
+
865 
+
866  case s_req_spaces_before_url:
+
867  {
+
868  if (ch == ' ') break;
+
869 
+
870  CROW_MARK(url);
+
871  CROW_MARK(url_start);
+
872  if (parser->method == (unsigned)HTTPMethod::Connect) {
+
873  parser->state = s_req_server_start;
+
874  }
+
875 
+
876  parser->state = parse_url_char(static_cast<state>(parser->state), ch, parser, url_start_mark, p);
+
877  if (CROW_UNLIKELY(parser->state == s_dead)) {
+
878  CROW_SET_ERRNO(CHPE_INVALID_URL);
+
879  goto error;
+
880  }
+
881 
+
882  break;
+
883  }
+
884 
+
885  case s_req_schema:
+
886  case s_req_schema_slash:
+
887  case s_req_schema_slash_slash:
+
888  case s_req_server_start:
+
889  {
+
890  switch (ch) {
+
891  /* No whitespace allowed here */
+
892  case ' ':
+
893  case cr:
+
894  case lf:
+
895  CROW_SET_ERRNO(CHPE_INVALID_URL);
+
896  goto error;
+
897  default:
+
898  parser->state = parse_url_char(static_cast<state>(parser->state), ch, parser, url_start_mark, p);
+
899  if (CROW_UNLIKELY(parser->state == s_dead)) {
+
900  CROW_SET_ERRNO(CHPE_INVALID_URL);
+
901  goto error;
+
902  }
+
903  }
+
904 
+
905  break;
+
906  }
+
907 
+
908  case s_req_server:
+
909  case s_req_server_with_at:
+
910  case s_req_path:
+
911  case s_req_query_string_start:
+
912  case s_req_query_string:
+
913  {
+
914  switch (ch) {
+
915  case ' ':
+
916  parser->state = s_req_http_start;
+
917  CROW_CALLBACK_DATA(url);
+
918  break;
+
919  case cr: // No space after URL means no HTTP version. Which means the request is using HTTP/0.9
+
920  case lf:
+
921  if (CROW_UNLIKELY(parser->method != (unsigned)HTTPMethod::Get)) // HTTP/0.9 doesn't define any method other than GET
+
922  {
+
923  parser->state = s_dead;
+
924  CROW_SET_ERRNO(CHPE_INVALID_VERSION);
+
925  goto error;
+
926  }
+
927  parser->http_major = 0;
+
928  parser->http_minor = 9;
+
929  parser->state = (ch == cr) ?
+
930  s_req_line_almost_done :
+
931  s_header_field_start;
+
932  CROW_CALLBACK_DATA(url);
+
933  break;
+
934  default:
+
935  parser->state = parse_url_char(static_cast<state>(parser->state), ch, parser, url_start_mark, p);
+
936  if (CROW_UNLIKELY(parser->state == s_dead)) {
+
937  CROW_SET_ERRNO(CHPE_INVALID_URL);
+
938  goto error;
+
939  }
+
940  }
+
941  break;
+
942  }
+
943 
+
944  case s_req_http_start:
+
945  switch (ch) {
+
946  case ' ':
+
947  break;
+
948  case 'H':
+
949  parser->state = s_req_http_H;
+
950  break;
+
951  case 'I':
+
952  if (parser->method == (unsigned)HTTPMethod::Source) {
+
953  parser->state = s_req_http_I;
+
954  break;
+
955  }
+
956  /* fall through */
+
957  default:
+
958  CROW_SET_ERRNO(CHPE_INVALID_CONSTANT);
+
959  goto error;
+
960  }
+
961  break;
+
962 
+
963  case s_req_http_H:
+
964  CROW_STRICT_CHECK(ch != 'T');
+
965  parser->state = s_req_http_HT;
+
966  break;
+
967 
+
968  case s_req_http_HT:
+
969  CROW_STRICT_CHECK(ch != 'T');
+
970  parser->state = s_req_http_HTT;
+
971  break;
+
972 
+
973  case s_req_http_HTT:
+
974  CROW_STRICT_CHECK(ch != 'P');
+
975  parser->state = s_req_http_HTTP;
+
976  break;
+
977 
+
978  case s_req_http_I:
+
979  CROW_STRICT_CHECK(ch != 'C');
+
980  parser->state = s_req_http_IC;
+
981  break;
+
982 
+
983  case s_req_http_IC:
+
984  CROW_STRICT_CHECK(ch != 'E');
+
985  parser->state = s_req_http_HTTP; /* Treat "ICE" as "HTTP". */
+
986  break;
+
987 
+
988  case s_req_http_HTTP:
+
989  CROW_STRICT_CHECK(ch != '/');
+
990  parser->state = s_req_http_major;
+
991  break;
+
992 
+
993  /* dot */
+
994  case s_req_http_major:
+
995  if (CROW_UNLIKELY(!CROW_IS_NUM(ch))) {
+
996  CROW_SET_ERRNO(CHPE_INVALID_VERSION);
+
997  goto error;
+
998  }
+
999 
+
1000  parser->http_major = ch - '0';
+
1001  parser->state = s_req_http_dot;
+
1002  break;
+
1003 
+
1004  case s_req_http_dot:
+
1005  {
+
1006  if (CROW_UNLIKELY(ch != '.')) {
+
1007  CROW_SET_ERRNO(CHPE_INVALID_VERSION);
+
1008  goto error;
+
1009  }
+
1010 
+
1011  parser->state = s_req_http_minor;
+
1012  break;
+
1013  }
+
1014 
+
1015  /* minor HTTP version */
+
1016  case s_req_http_minor:
+
1017  if (CROW_UNLIKELY(!CROW_IS_NUM(ch))) {
+
1018  CROW_SET_ERRNO(CHPE_INVALID_VERSION);
+
1019  goto error;
+
1020  }
+
1021 
+
1022  parser->http_minor = ch - '0';
+
1023  parser->state = s_req_http_end;
+
1024  break;
+
1025 
+
1026  /* end of request line */
+
1027  case s_req_http_end:
+
1028  {
+
1029  if (ch == cr) {
+
1030  parser->state = s_req_line_almost_done;
+
1031  break;
+
1032  }
+
1033 
+
1034  if (ch == lf) {
+
1035  parser->state = s_header_field_start;
+
1036  break;
+
1037  }
+
1038 
+
1039  CROW_SET_ERRNO(CHPE_INVALID_VERSION);
+
1040  goto error;
+
1041  break;
+
1042  }
+
1043 
+
1044  /* end of request line */
+
1045  case s_req_line_almost_done:
+
1046  {
+
1047  if (CROW_UNLIKELY(ch != lf)) {
+
1048  CROW_SET_ERRNO(CHPE_LF_EXPECTED);
+
1049  goto error;
+
1050  }
+
1051 
+
1052  parser->state = s_header_field_start;
+
1053  break;
+
1054  }
+
1055 
+
1056  case s_header_field_start:
+
1057  {
+
1058  if (ch == cr) {
+
1059  parser->state = s_headers_almost_done;
+
1060  break;
+
1061  }
+
1062 
+
1063  if (ch == lf) {
+
1064  /* they might be just sending \n instead of \r\n so this would be
+
1065  * the second \n to denote the end of headers*/
+
1066  parser->state = s_headers_almost_done;
+
1067  CROW_REEXECUTE();
+
1068  }
+
1069 
+
1070  c = CROW_TOKEN(ch);
+
1071 
+
1072  if (CROW_UNLIKELY(!c)) {
+
1073  CROW_SET_ERRNO(CHPE_INVALID_HEADER_TOKEN);
+
1074  goto error;
+
1075  }
+
1076 
+
1077  CROW_MARK(header_field);
+
1078 
+
1079  parser->index = 0;
+
1080  parser->state = s_header_field;
+
1081 
+
1082  switch (c) {
+
1083  case 'c':
+
1084  parser->header_state = h_C;
+
1085  break;
+
1086 
+
1087  case 'p':
+
1088  parser->header_state = h_matching_proxy_connection;
+
1089  break;
+
1090 
+
1091  case 't':
+
1092  parser->header_state = h_matching_transfer_encoding;
+
1093  break;
+
1094 
+
1095  case 'u':
+
1096  parser->header_state = h_matching_upgrade;
+
1097  break;
+
1098 
+
1099  default:
+
1100  parser->header_state = h_general;
+
1101  break;
+
1102  }
+
1103  break;
+
1104  }
+
1105 
+
1106  case s_header_field:
+
1107  {
+
1108  const char* start = p;
+
1109  for (; p != data + len; p++) {
+
1110  ch = *p;
+
1111  c = CROW_TOKEN(ch);
+
1112 
+
1113  if (!c)
+
1114  break;
+
1115 
+
1116  switch (parser->header_state) {
+
1117  case h_general: {
+
1118  size_t left = data + len - p;
+
1119  const char* pe = p + CROW_MIN(left, max_header_size);
+
1120  while (p+1 < pe && CROW_TOKEN(p[1])) {
+
1121  p++;
+
1122  }
+
1123  break;
+
1124  }
+
1125 
+
1126  case h_C:
+
1127  parser->index++;
+
1128  parser->header_state = (c == 'o' ? h_CO : h_general);
+
1129  break;
+
1130 
+
1131  case h_CO:
+
1132  parser->index++;
+
1133  parser->header_state = (c == 'n' ? h_CON : h_general);
+
1134  break;
+
1135 
+
1136  case h_CON:
+
1137  parser->index++;
+
1138  switch (c) {
+
1139  case 'n':
+
1140  parser->header_state = h_matching_connection;
+
1141  break;
+
1142  case 't':
+
1143  parser->header_state = h_matching_content_length;
+
1144  break;
+
1145  default:
+
1146  parser->header_state = h_general;
+
1147  break;
+
1148  }
+
1149  break;
+
1150 
+
1151  /* connection */
+
1152 
+
1153  case h_matching_connection:
+
1154  parser->index++;
+
1155  if (parser->index > sizeof(CROW_CONNECTION)-1 || c != CROW_CONNECTION[parser->index]) {
+
1156  parser->header_state = h_general;
+
1157  } else if (parser->index == sizeof(CROW_CONNECTION)-2) {
+
1158  parser->header_state = h_connection;
+
1159  }
+
1160  break;
+
1161 
+
1162  /* proxy-connection */
+
1163 
+
1164  case h_matching_proxy_connection:
+
1165  parser->index++;
+
1166  if (parser->index > sizeof(CROW_PROXY_CONNECTION)-1 || c != CROW_PROXY_CONNECTION[parser->index]) {
+
1167  parser->header_state = h_general;
+
1168  } else if (parser->index == sizeof(CROW_PROXY_CONNECTION)-2) {
+
1169  parser->header_state = h_connection;
+
1170  }
+
1171  break;
+
1172 
+
1173  /* content-length */
+
1174 
+
1175  case h_matching_content_length:
+
1176  parser->index++;
+
1177  if (parser->index > sizeof(CROW_CONTENT_LENGTH)-1 || c != CROW_CONTENT_LENGTH[parser->index]) {
+
1178  parser->header_state = h_general;
+
1179  } else if (parser->index == sizeof(CROW_CONTENT_LENGTH)-2) {
+
1180  parser->header_state = h_content_length;
+
1181  }
+
1182  break;
+
1183 
+
1184  /* transfer-encoding */
+
1185 
+
1186  case h_matching_transfer_encoding:
+
1187  parser->index++;
+
1188  if (parser->index > sizeof(CROW_TRANSFER_ENCODING)-1 || c != CROW_TRANSFER_ENCODING[parser->index]) {
+
1189  parser->header_state = h_general;
+
1190  } else if (parser->index == sizeof(CROW_TRANSFER_ENCODING)-2) {
+
1191  parser->header_state = h_transfer_encoding;
+
1192  parser->uses_transfer_encoding = 1;
+
1193  }
+
1194  break;
+
1195 
+
1196  /* upgrade */
+
1197 
+
1198  case h_matching_upgrade:
+
1199  parser->index++;
+
1200  if (parser->index > sizeof(CROW_UPGRADE)-1 || c != CROW_UPGRADE[parser->index]) {
+
1201  parser->header_state = h_general;
+
1202  } else if (parser->index == sizeof(CROW_UPGRADE)-2) {
+
1203  parser->header_state = h_upgrade;
+
1204  }
+
1205  break;
+
1206 
+
1207  case h_connection:
+
1208  case h_content_length:
+
1209  case h_transfer_encoding:
+
1210  case h_upgrade:
+
1211  if (ch != ' ') parser->header_state = h_general;
+
1212  break;
+
1213 
+
1214  default:
+
1215  assert(0 && "Unknown header_state");
+
1216  break;
+
1217  }
+
1218  }
+
1219 
+
1220  if (p == data + len) {
+
1221  --p;
+
1222  CROW_COUNT_HEADER_SIZE(p - start);
+
1223  break;
+
1224  }
+
1225 
+
1226  CROW_COUNT_HEADER_SIZE(p - start);
+
1227 
+
1228  if (ch == ':') {
+
1229  parser->state = s_header_value_discard_ws;
+
1230  CROW_CALLBACK_DATA(header_field);
+
1231  break;
+
1232  }
+
1233 /* RFC-7230 Sec 3.2.4 expressly forbids line-folding in header field-names.
+
1234  if (ch == cr) {
+
1235  parser->state = s_header_almost_done;
+
1236  CROW_CALLBACK_DATA(header_field);
+
1237  break;
+
1238  }
+
1239 
+
1240  if (ch == lf) {
+
1241  parser->state = s_header_field_start;
+
1242  CROW_CALLBACK_DATA(header_field);
+
1243  break;
+
1244  }
+
1245 */
+
1246  CROW_SET_ERRNO(CHPE_INVALID_HEADER_TOKEN);
+
1247  goto error;
+
1248  }
+
1249 
+
1250  case s_header_value_discard_ws:
+
1251  if (ch == ' ' || ch == '\t') break;
+
1252 
+
1253  if (ch == cr) {
+
1254  parser->state = s_header_value_discard_ws_almost_done;
+
1255  break;
+
1256  }
+
1257 
+
1258  if (ch == lf) {
+
1259  parser->state = s_header_value_discard_lws;
+
1260  break;
+
1261  }
+
1262 
+
1263  /* fall through */
+
1264 
+
1265  case s_header_value_start:
+
1266  {
+
1267  CROW_MARK(header_value);
+
1268 
+
1269  parser->state = s_header_value;
+
1270  parser->index = 0;
+
1271 
+
1272  c = CROW_LOWER(ch);
+
1273 
+
1274  switch (parser->header_state) {
+
1275  case h_upgrade:
+
1276  // Crow does not support HTTP/2 at the moment.
+
1277  // According to the RFC https://datatracker.ietf.org/doc/html/rfc7540#section-3.2
+
1278  // "A server that does not support HTTP/2 can respond to the request as though the Upgrade header field were absent"
+
1279  // => `F_UPGRADE` is not set if the header starts by "h2".
+
1280  // This prevents the parser from skipping the request body.
+
1281  if (ch != 'h' || p+1 == (data + len) || *(p+1) != '2') {
+
1282  parser->flags |= F_UPGRADE;
+
1283  }
+
1284  parser->header_state = h_general;
+
1285  break;
+
1286 
+
1287  case h_transfer_encoding:
+
1288  /* looking for 'Transfer-Encoding: chunked' */
+
1289  if ('c' == c) {
+
1290  parser->header_state = h_matching_transfer_encoding_chunked;
+
1291  } else {
+
1292  parser->header_state = h_matching_transfer_encoding_token;
+
1293  }
+
1294  break;
+
1295 
+
1296  /* Multi-value `Transfer-Encoding` header */
+
1297  case h_matching_transfer_encoding_token_start:
+
1298  break;
+
1299 
+
1300  case h_content_length:
+
1301  if (CROW_UNLIKELY(!CROW_IS_NUM(ch))) {
+
1302  CROW_SET_ERRNO(CHPE_INVALID_CONTENT_LENGTH);
+
1303  goto error;
+
1304  }
+
1305 
+
1306  if (parser->flags & F_CONTENTLENGTH) {
+
1307  CROW_SET_ERRNO(CHPE_UNEXPECTED_CONTENT_LENGTH);
+
1308  goto error;
+
1309  }
+
1310  parser->flags |= F_CONTENTLENGTH;
+
1311  parser->content_length = ch - '0';
+
1312  parser->header_state = h_content_length_num;
+
1313  break;
+
1314 
+
1315  /* when obsolete line folding is encountered for content length
+
1316  * continue to the s_header_value state */
+
1317  case h_content_length_ws:
+
1318  break;
+
1319 
+
1320  case h_connection:
+
1321  /* looking for 'Connection: keep-alive' */
+
1322  if (c == 'k') {
+
1323  parser->header_state = h_matching_connection_keep_alive;
+
1324  /* looking for 'Connection: close' */
+
1325  } else if (c == 'c') {
+
1326  parser->header_state = h_matching_connection_close;
+
1327  } else if (c == ' ' || c == '\t') {
+
1328  /* Skip lws */
+
1329  } else {
+
1330  parser->header_state = h_general;
+
1331  }
+
1332  break;
+
1333 
+
1334  default:
+
1335  parser->header_state = h_general;
+
1336  break;
+
1337  }
+
1338  break;
+
1339  }
+
1340 
+
1341  case s_header_value:
+
1342  {
+
1343  const char* start = p;
+
1344  enum header_states h_state = static_cast<header_states>(parser->header_state);
+
1345  for (; p != data + len; p++) {
+
1346  ch = *p;
+
1347 
+
1348  if (ch == cr) {
+
1349  parser->state = s_header_almost_done;
+
1350  parser->header_state = h_state;
+
1351  CROW_CALLBACK_DATA(header_value);
+
1352  break;
+
1353  }
+
1354 
+
1355  if (ch == lf) {
+
1356  parser->state = s_header_almost_done;
+
1357  CROW_COUNT_HEADER_SIZE(p - start);
+
1358  parser->header_state = h_state;
+
1359  CROW_CALLBACK_DATA_NOADVANCE(header_value);
+
1360  CROW_REEXECUTE();
+
1361  }
+
1362 
+
1363  if (!lenient && !CROW_IS_HEADER_CHAR(ch)) {
+
1364  CROW_SET_ERRNO(CHPE_INVALID_HEADER_TOKEN);
+
1365  goto error;
+
1366  }
+
1367 
+
1368  c = CROW_LOWER(ch);
+
1369 
+
1370  switch (h_state) {
+
1371  case h_general:
+
1372  {
+
1373  size_t left = data + len - p;
+
1374  const char* pe = p + CROW_MIN(left, max_header_size);
+
1375 
+
1376  for (; p != pe; p++) {
+
1377  ch = *p;
+
1378  if (ch == cr || ch == lf) {
+
1379  --p;
+
1380  break;
+
1381  }
+
1382  if (!lenient && !CROW_IS_HEADER_CHAR(ch)) {
+
1383  CROW_SET_ERRNO(CHPE_INVALID_HEADER_TOKEN);
+
1384  goto error;
+
1385  }
+
1386  }
+
1387  if (p == data + len)
+
1388  --p;
+
1389  break;
+
1390  }
+
1391 
+
1392  case h_connection:
+
1393  case h_transfer_encoding:
+
1394  assert(0 && "Shouldn't get here.");
+
1395  break;
+
1396 
+
1397  case h_content_length:
+
1398  if (ch == ' ') break;
+
1399  h_state = h_content_length_num;
+
1400  /* fall through */
+
1401 
+
1402  case h_content_length_num:
+
1403  {
+
1404  uint64_t t;
+
1405 
+
1406  if (ch == ' ') {
+
1407  h_state = h_content_length_ws;
+
1408  break;
+
1409  }
+
1410 
+
1411  if (CROW_UNLIKELY(!CROW_IS_NUM(ch))) {
+
1412  CROW_SET_ERRNO(CHPE_INVALID_CONTENT_LENGTH);
+
1413  parser->header_state = h_state;
+
1414  goto error;
+
1415  }
+
1416 
+
1417  t = parser->content_length;
+
1418  t *= 10;
+
1419  t += ch - '0';
+
1420 
+
1421  /* Overflow? Test against a conservative limit for simplicity. */
+
1422  if (CROW_UNLIKELY((CROW_ULLONG_MAX - 10) / 10 < parser->content_length)) {
+
1423  CROW_SET_ERRNO(CHPE_INVALID_CONTENT_LENGTH);
+
1424  parser->header_state = h_state;
+
1425  goto error;
+
1426  }
+
1427 
+
1428  parser->content_length = t;
+
1429  break;
+
1430  }
+
1431 
+
1432  case h_content_length_ws:
+
1433  if (ch == ' ') break;
+
1434  CROW_SET_ERRNO(CHPE_INVALID_CONTENT_LENGTH);
+
1435  parser->header_state = h_state;
+
1436  goto error;
+
1437 
+
1438  /* Transfer-Encoding: chunked */
+
1439  case h_matching_transfer_encoding_token_start:
+
1440  /* looking for 'Transfer-Encoding: chunked' */
+
1441  if ('c' == c) {
+
1442  h_state = h_matching_transfer_encoding_chunked;
+
1443  } else if (CROW_TOKEN(c)) {
+
1444  /* TODO(indutny): similar code below does this, but why?
+
1445  * At the very least it seems to be inconsistent given that
+
1446  * h_matching_transfer_encoding_token does not check for
+
1447  * `STRICT_TOKEN`
+
1448  */
+
1449  h_state = h_matching_transfer_encoding_token;
+
1450  } else if (c == ' ' || c == '\t') {
+
1451  /* Skip lws */
+
1452  } else {
+
1453  h_state = h_general;
+
1454  }
+
1455  break;
+
1456 
+
1457  case h_matching_transfer_encoding_chunked:
+
1458  parser->index++;
+
1459  if (parser->index > sizeof(CROW_CHUNKED)-1 || c != CROW_CHUNKED[parser->index]) {
+
1460  h_state = h_matching_transfer_encoding_token;
+
1461  } else if (parser->index == sizeof(CROW_CHUNKED)-2) {
+
1462  h_state = h_transfer_encoding_chunked;
+
1463  }
+
1464  break;
+
1465 
+
1466  case h_matching_transfer_encoding_token:
+
1467  if (ch == ',') {
+
1468  h_state = h_matching_transfer_encoding_token_start;
+
1469  parser->index = 0;
+
1470  }
+
1471  break;
+
1472 
+
1473  /* looking for 'Connection: keep-alive' */
+
1474  case h_matching_connection_keep_alive:
+
1475  parser->index++;
+
1476  if (parser->index > sizeof(CROW_KEEP_ALIVE)-1 || c != CROW_KEEP_ALIVE[parser->index]) {
+
1477  h_state = h_general;
+
1478  } else if (parser->index == sizeof(CROW_KEEP_ALIVE)-2) {
+
1479  h_state = h_connection_keep_alive;
+
1480  }
+
1481  break;
+
1482 
+
1483  /* looking for 'Connection: close' */
+
1484  case h_matching_connection_close:
+
1485  parser->index++;
+
1486  if (parser->index > sizeof(CROW_CLOSE)-1 || c != CROW_CLOSE[parser->index]) {
+
1487  h_state = h_general;
+
1488  } else if (parser->index == sizeof(CROW_CLOSE)-2) {
+
1489  h_state = h_connection_close;
+
1490  }
+
1491  break;
+
1492 
+
1493  // Edited from original (because of commits that werent included)
+
1494  case h_transfer_encoding_chunked:
+
1495  if (ch != ' ') h_state = h_matching_transfer_encoding_token;
+
1496  break;
+
1497  case h_connection_keep_alive:
+
1498  case h_connection_close:
+
1499  if (ch != ' ') h_state = h_general;
+
1500  break;
+
1501 
+
1502  default:
+
1503  parser->state = s_header_value;
+
1504  h_state = h_general;
+
1505  break;
+
1506  }
+
1507  }
+
1508  parser->header_state = h_state;
+
1509 
+
1510 
+
1511  if (p == data + len)
+
1512  --p;
+
1513 
+
1514  CROW_COUNT_HEADER_SIZE(p - start);
+
1515  break;
+
1516  }
+
1517 
+
1518  case s_header_almost_done:
+
1519  {
+
1520  if (CROW_UNLIKELY(ch != lf)) {
+
1521  CROW_SET_ERRNO(CHPE_LF_EXPECTED);
+
1522  goto error;
+
1523  }
+
1524 
+
1525  parser->state = s_header_value_lws;
+
1526  break;
+
1527  }
+
1528 
+
1529  case s_header_value_lws:
+
1530  {
+
1531  if (ch == ' ' || ch == '\t') {
+
1532  if (parser->header_state == h_content_length_num) {
+
1533  /* treat obsolete line folding as space */
+
1534  parser->header_state = h_content_length_ws;
+
1535  }
+
1536  parser->state = s_header_value_start;
+
1537  CROW_REEXECUTE();
+
1538  }
+
1539 
+
1540  /* finished the header */
+
1541  switch (parser->header_state) {
+
1542  case h_connection_keep_alive:
+
1543  parser->flags |= F_CONNECTION_KEEP_ALIVE;
+
1544  break;
+
1545  case h_connection_close:
+
1546  parser->flags |= F_CONNECTION_CLOSE;
+
1547  break;
+
1548  case h_transfer_encoding_chunked:
+
1549  parser->flags |= F_CHUNKED;
+
1550  break;
+
1551  default:
+
1552  break;
+
1553  }
+
1554 
+
1555  parser->state = s_header_field_start;
+
1556  CROW_REEXECUTE();
+
1557  }
+
1558 
+
1559  case s_header_value_discard_ws_almost_done:
+
1560  {
+
1561  CROW_STRICT_CHECK(ch != lf);
+
1562  parser->state = s_header_value_discard_lws;
+
1563  break;
+
1564  }
+
1565 
+
1566  case s_header_value_discard_lws:
+
1567  {
+
1568  if (ch == ' ' || ch == '\t') {
+
1569  parser->state = s_header_value_discard_ws;
+
1570  break;
+
1571  } else {
+
1572  /* header value was empty */
+
1573  CROW_MARK(header_value);
+
1574  parser->state = s_header_field_start;
+
1575  CROW_CALLBACK_DATA_NOADVANCE(header_value);
+
1576  CROW_REEXECUTE();
+
1577  }
+
1578  }
+
1579 
+
1580  case s_headers_almost_done:
+
1581  {
+
1582  CROW_STRICT_CHECK(ch != lf);
+
1583 
+
1584  if (parser->flags & F_TRAILING) {
+
1585  /* End of a chunked request */
+
1586  CROW_CALLBACK_NOTIFY(message_complete);
+
1587  break;
+
1588  }
+
1589 
+
1590  /* Cannot use transfer-encoding and a content-length header together
+
1591  per the HTTP specification. (RFC 7230 Section 3.3.3) */
+
1592  if ((parser->uses_transfer_encoding == 1) &&
+
1593  (parser->flags & F_CONTENTLENGTH)) {
+
1594  /* Allow it for lenient parsing as long as `Transfer-Encoding` is
+
1595  * not `chunked` or allow_length_with_encoding is set
+
1596  */
+
1597  if (parser->flags & F_CHUNKED) {
+
1598  if (!allow_chunked_length) {
+
1599  CROW_SET_ERRNO(CHPE_UNEXPECTED_CONTENT_LENGTH);
+
1600  goto error;
+
1601  }
+
1602  } else if (!lenient) {
+
1603  CROW_SET_ERRNO(CHPE_UNEXPECTED_CONTENT_LENGTH);
+
1604  goto error;
+
1605  }
+
1606  }
+
1607 
+
1608  parser->state = s_headers_done;
+
1609 
+
1610  /* Set this here so that on_headers_complete() callbacks can see it */
+
1611  parser->upgrade =
+
1612  (parser->flags & F_UPGRADE || parser->method == (unsigned)HTTPMethod::Connect);
+
1613 
+
1614  /* Here we call the headers_complete callback. This is somewhat
+
1615  * different than other callbacks because if the user returns 1, we
+
1616  * will interpret that as saying that this message has no body. This
+
1617  * is needed for the annoying case of recieving a response to a HEAD
+
1618  * request.
+
1619  *
+
1620  * We'd like to use CROW_CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so
+
1621  * we have to simulate it by handling a change in errno below.
+
1622  */
+
1623  if (settings->on_headers_complete) {
+
1624  switch (settings->on_headers_complete(parser)) {
+
1625  case 0:
+
1626  break;
+
1627 
+
1628  case 2:
+
1629  parser->upgrade = 1;
+
1630  //break;
+
1631 
+
1632  /* fall through */
+
1633  case 1:
+
1634  parser->flags |= F_SKIPBODY;
+
1635  break;
+
1636 
+
1637  default:
+
1638  CROW_SET_ERRNO(CHPE_CB_headers_complete);
+
1639  parser->nread = nread;
+
1640  return p - data; /* Error */
+
1641  }
+
1642  }
+
1643 
+
1644  if (CROW_HTTP_PARSER_ERRNO(parser) != CHPE_OK) {
+
1645  parser->nread = nread;
+
1646  return p - data;
+
1647  }
+
1648 
+
1649  CROW_REEXECUTE();
+
1650  }
+
1651 
+
1652  case s_headers_done:
+
1653  {
+
1654  CROW_STRICT_CHECK(ch != lf);
+
1655 
+
1656  parser->nread = 0;
+
1657  nread = 0;
+
1658 
+
1659  /* Exit, the rest of the connect is in a different protocol. */
+
1660  if (parser->upgrade) {
+
1661  CROW_CALLBACK_NOTIFY(message_complete);
+
1662  parser->nread = nread;
+
1663  return (p - data) + 1;
+
1664  }
+
1665 
+
1666  if (parser->flags & F_SKIPBODY) {
+
1667  CROW_CALLBACK_NOTIFY(message_complete);
+
1668  } else if (parser->flags & F_CHUNKED) {
+
1669  /* chunked encoding - ignore Content-Length header,
+
1670  * prepare for a chunk */
+
1671  parser->state = s_chunk_size_start;
+
1672  }
+
1673  else if (parser->uses_transfer_encoding == 1)
+
1674  {
+
1675  if (!lenient)
+
1676  {
+
1677  /* RFC 7230 3.3.3 */
+
1678 
+
1679  /* If a Transfer-Encoding header field
+
1680  * is present in a request and the chunked transfer coding is not
+
1681  * the final encoding, the message body length cannot be determined
+
1682  * reliably; the server MUST respond with the 400 (Bad Request)
+
1683  * status code and then close the connection.
+
1684  */
+
1685  CROW_SET_ERRNO(CHPE_INVALID_TRANSFER_ENCODING);
+
1686  parser->nread = nread;
+
1687  return (p - data); /* Error */
+
1688  }
+
1689  else
+
1690  {
+
1691  /* RFC 7230 3.3.3 */
+
1692 
+
1693  /* If a Transfer-Encoding header field is present in a response and
+
1694  * the chunked transfer coding is not the final encoding, the
+
1695  * message body length is determined by reading the connection until
+
1696  * it is closed by the server.
+
1697  */
+
1698  parser->state = s_body_identity_eof;
+
1699  }
+
1700  }
+
1701  else
+
1702  {
+
1703  if (parser->content_length == 0)
+
1704  {
+
1705  /* Content-Length header given but zero: Content-Length: 0\r\n */
+
1706  CROW_CALLBACK_NOTIFY(message_complete);
+
1707  }
+
1708  else if (parser->content_length != CROW_ULLONG_MAX)
+
1709  {
+
1710  /* Content-Length header given and non-zero */
+
1711  parser->state = s_body_identity;
+
1712  }
+
1713  else
+
1714  {
+
1715  /* Assume content-length 0 - read the next */
+
1716  CROW_CALLBACK_NOTIFY(message_complete);
+
1717  }
+
1718  }
+
1719 
+
1720  break;
+
1721  }
+
1722 
+
1723  case s_body_identity:
+
1724  {
+
1725  uint64_t to_read = CROW_MIN(parser->content_length,
+
1726  (uint64_t) ((data + len) - p));
+
1727 
+
1728  assert(parser->content_length != 0
+
1729  && parser->content_length != CROW_ULLONG_MAX);
+
1730 
+
1731  /* The difference between advancing content_length and p is because
+
1732  * the latter will automaticaly advance on the next loop iteration.
+
1733  * Further, if content_length ends up at 0, we want to see the last
+
1734  * byte again for our message complete callback.
+
1735  */
+
1736  CROW_MARK(body);
+
1737  parser->content_length -= to_read;
+
1738  p += to_read - 1;
+
1739 
+
1740  if (parser->content_length == 0) {
+
1741  parser->state = s_message_done;
+
1742 
+
1743  /* Mimic CROW_CALLBACK_DATA_NOADVANCE() but with one extra byte.
+
1744  *
+
1745  * The alternative to doing this is to wait for the next byte to
+
1746  * trigger the data callback, just as in every other case. The
+
1747  * problem with this is that this makes it difficult for the test
+
1748  * harness to distinguish between complete-on-EOF and
+
1749  * complete-on-length. It's not clear that this distinction is
+
1750  * important for applications, but let's keep it for now.
+
1751  */
+
1752  CROW_CALLBACK_DATA_(body, p - body_mark + 1, p - data);
+
1753  CROW_REEXECUTE();
+
1754  }
+
1755 
+
1756  break;
+
1757  }
+
1758 
+
1759  /* read until EOF */
+
1760  case s_body_identity_eof:
+
1761  CROW_MARK(body);
+
1762  p = data + len - 1;
+
1763 
+
1764  break;
+
1765 
+
1766  case s_message_done:
+
1767  CROW_CALLBACK_NOTIFY(message_complete);
+
1768  break;
+
1769 
+
1770  case s_chunk_size_start:
+
1771  {
+
1772  assert(nread == 1);
+
1773  assert(parser->flags & F_CHUNKED);
+
1774 
+
1775  unhex_val = unhex[static_cast<unsigned char>(ch)];
+
1776  if (CROW_UNLIKELY(unhex_val == -1)) {
+
1777  CROW_SET_ERRNO(CHPE_INVALID_CHUNK_SIZE);
+
1778  goto error;
+
1779  }
+
1780 
+
1781  parser->content_length = unhex_val;
+
1782  parser->state = s_chunk_size;
+
1783  break;
+
1784  }
+
1785 
+
1786  case s_chunk_size:
+
1787  {
+
1788  uint64_t t;
+
1789 
+
1790  assert(parser->flags & F_CHUNKED);
+
1791 
+
1792  if (ch == cr) {
+
1793  parser->state = s_chunk_size_almost_done;
+
1794  break;
+
1795  }
+
1796 
+
1797  unhex_val = unhex[static_cast<unsigned char>(ch)];
+
1798 
+
1799  if (unhex_val == -1) {
+
1800  if (ch == ';' || ch == ' ') {
+
1801  parser->state = s_chunk_parameters;
+
1802  break;
+
1803  }
+
1804 
+
1805  CROW_SET_ERRNO(CHPE_INVALID_CHUNK_SIZE);
+
1806  goto error;
+
1807  }
+
1808 
+
1809  t = parser->content_length;
+
1810  t *= 16;
+
1811  t += unhex_val;
+
1812 
+
1813  /* Overflow? Test against a conservative limit for simplicity. */
+
1814  if (CROW_UNLIKELY((CROW_ULLONG_MAX - 16) / 16 < parser->content_length)) {
+
1815  CROW_SET_ERRNO(CHPE_INVALID_CONTENT_LENGTH);
+
1816  goto error;
+
1817  }
+
1818 
+
1819  parser->content_length = t;
+
1820  break;
+
1821  }
+
1822 
+
1823  case s_chunk_parameters:
+
1824  {
+
1825  assert(parser->flags & F_CHUNKED);
+
1826  /* just ignore this shit. TODO check for overflow */
+
1827  if (ch == cr) {
+
1828  parser->state = s_chunk_size_almost_done;
+
1829  break;
+
1830  }
+
1831  break;
+
1832  }
+
1833 
+
1834  case s_chunk_size_almost_done:
+
1835  {
+
1836  assert(parser->flags & F_CHUNKED);
+
1837  CROW_STRICT_CHECK(ch != lf);
+
1838 
+
1839  parser->nread = 0;
+
1840  nread = 0;
+
1841 
+
1842  if (parser->content_length == 0) {
+
1843  parser->flags |= F_TRAILING;
+
1844  parser->state = s_header_field_start;
+
1845  } else {
+
1846  parser->state = s_chunk_data;
+
1847  }
+
1848  break;
+
1849  }
+
1850 
+
1851  case s_chunk_data:
+
1852  {
+
1853  uint64_t to_read = CROW_MIN(parser->content_length,
+
1854  (uint64_t) ((data + len) - p));
+
1855 
+
1856  assert(parser->flags & F_CHUNKED);
+
1857  assert(parser->content_length != 0
+
1858  && parser->content_length != CROW_ULLONG_MAX);
+
1859 
+
1860  /* See the explanation in s_body_identity for why the content
+
1861  * length and data pointers are managed this way.
+
1862  */
+
1863  CROW_MARK(body);
+
1864  parser->content_length -= to_read;
+
1865  p += to_read - 1;
+
1866 
+
1867  if (parser->content_length == 0) {
+
1868  parser->state = s_chunk_data_almost_done;
+
1869  }
+
1870 
+
1871  break;
+
1872  }
+
1873 
+
1874  case s_chunk_data_almost_done:
+
1875  assert(parser->flags & F_CHUNKED);
+
1876  assert(parser->content_length == 0);
+
1877  CROW_STRICT_CHECK(ch != cr);
+
1878  parser->state = s_chunk_data_done;
+
1879  CROW_CALLBACK_DATA(body);
+
1880  break;
+
1881 
+
1882  case s_chunk_data_done:
+
1883  assert(parser->flags & F_CHUNKED);
+
1884  CROW_STRICT_CHECK(ch != lf);
+
1885  parser->nread = 0;
+
1886  nread = 0;
+
1887  parser->state = s_chunk_size_start;
+
1888  break;
+
1889 
+
1890  default:
+
1891  assert(0 && "unhandled state");
+
1892  CROW_SET_ERRNO(CHPE_INVALID_INTERNAL_STATE);
+
1893  goto error;
+
1894  }
+
1895  }
+
1896 
+
1897  /* Run callbacks for any marks that we have leftover after we ran out of
+
1898  * bytes. There should be at most one of these set, so it's OK to invoke
+
1899  * them in series (unset marks will not result in callbacks).
+
1900  *
+
1901  * We use the NOADVANCE() variety of callbacks here because 'p' has already
+
1902  * overflowed 'data' and this allows us to correct for the off-by-one that
+
1903  * we'd otherwise have (since CROW_CALLBACK_DATA() is meant to be run with a 'p'
+
1904  * value that's in-bounds).
+
1905  */
+
1906 
+
1907  assert(((header_field_mark ? 1 : 0) +
+
1908  (header_value_mark ? 1 : 0) +
+
1909  (url_mark ? 1 : 0) +
+
1910  (body_mark ? 1 : 0)) <= 1);
+
1911 
+
1912  CROW_CALLBACK_DATA_NOADVANCE(header_field);
+
1913  CROW_CALLBACK_DATA_NOADVANCE(header_value);
+
1914  CROW_CALLBACK_DATA_NOADVANCE(url);
+
1915  CROW_CALLBACK_DATA_NOADVANCE(body);
+
1916 
+
1917  parser->nread = nread;
+
1918  return len;
+
1919 
+
1920 error:
+
1921  if (CROW_HTTP_PARSER_ERRNO(parser) == CHPE_OK) {
+
1922  CROW_SET_ERRNO(CHPE_UNKNOWN);
+
1923  }
+
1924 
+
1925  parser->nread = nread;
+
1926  return (p - data);
+
1927 }
+
1928 
+
1929 inline void
+
1930  http_parser_init(http_parser* parser)
+
1931 {
+
1932  void *data = parser->data; /* preserve application data */
+
1933  memset(parser, 0, sizeof(*parser));
+
1934  parser->data = data;
+
1935  parser->state = s_start_req;
+
1936  parser->http_errno = CHPE_OK;
+
1937 }
+
1938 
+
1939 /* Return a string name of the given error */
+
1940 inline const char *
+
1941 http_errno_name(enum http_errno err) {
+
1942 /* Map errno values to strings for human-readable output */
+
1943 #define CROW_HTTP_STRERROR_GEN(n, s) { "CHPE_" #n, s },
+
1944 static struct {
+
1945  const char *name;
+
1946  const char *description;
+
1947 } http_strerror_tab[] = {
+
1948  CROW_HTTP_ERRNO_MAP(CROW_HTTP_STRERROR_GEN)
+
1949 };
+
1950 #undef CROW_HTTP_STRERROR_GEN
+
1951  assert(((size_t) err) < CROW_ARRAY_SIZE(http_strerror_tab));
+
1952  return http_strerror_tab[err].name;
+
1953 }
+
1954 
+
1955 /* Return a string description of the given error */
+
1956 inline const char *
+
1957 http_errno_description(enum http_errno err) {
+
1958 /* Map errno values to strings for human-readable output */
+
1959 #define CROW_HTTP_STRERROR_GEN(n, s) { "CHPE_" #n, s },
+
1960 static struct {
+
1961  const char *name;
+
1962  const char *description;
+
1963 } http_strerror_tab[] = {
+
1964  CROW_HTTP_ERRNO_MAP(CROW_HTTP_STRERROR_GEN)
+
1965 };
+
1966 #undef CROW_HTTP_STRERROR_GEN
+
1967  assert(((size_t) err) < CROW_ARRAY_SIZE(http_strerror_tab));
+
1968  return http_strerror_tab[err].description;
+
1969 }
+
1970 
+
1971 /* Checks if this is the final chunk of the body. */
+
1972 inline int
+
1973 http_body_is_final(const struct http_parser *parser) {
+
1974  return parser->state == s_message_done;
+
1975 }
+
1976 
+
1977 /* Change the maximum header size provided at compile time. */
+
1978 inline void
+
1979 http_parser_set_max_header_size(uint32_t size) {
+
1980  max_header_size = size;
+
1981 }
+
1982 
+
1983 #undef CROW_HTTP_ERRNO_MAP
+
1984 #undef CROW_SET_ERRNO
+
1985 #undef CROW_CALLBACK_NOTIFY_
+
1986 #undef CROW_CALLBACK_NOTIFY
+
1987 #undef CROW_CALLBACK_NOTIFY_NOADVANCE
+
1988 #undef CROW_CALLBACK_DATA_
+
1989 #undef CROW_CALLBACK_DATA
+
1990 #undef CROW_CALLBACK_DATA_NOADVANCE
+
1991 #undef CROW_MARK
+
1992 #undef CROW_PROXY_CONNECTION
+
1993 #undef CROW_CONNECTION
+
1994 #undef CROW_CONTENT_LENGTH
+
1995 #undef CROW_TRANSFER_ENCODING
+
1996 #undef CROW_UPGRADE
+
1997 #undef CROW_CHUNKED
+
1998 #undef CROW_KEEP_ALIVE
+
1999 #undef CROW_CLOSE
+
2000 #undef CROW_PARSING_HEADER
+
2001 #undef CROW_LOWER
+
2002 #undef CROW_IS_ALPHA
+
2003 #undef CROW_IS_NUM
+
2004 #undef CROW_IS_ALPHANUM
+
2005 //#undef CROW_IS_HEX
+
2006 #undef CROW_IS_MARK
+
2007 #undef CROW_IS_USERINFO_CHAR
+
2008 #undef CROW_TOKEN
+
2009 #undef CROW_IS_URL_CHAR
+
2010 //#undef CROW_IS_HOST_CHAR
+
2011 #undef CROW_STRICT_CHECK
+
2012 
+
2013 }
+
2014 
+
2015 // clang-format on
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
Definition: http_parser_merged.h:181
+
Definition: http_parser_merged.h:148
+
unsigned char http_major
Definition: http_parser_merged.h:163
+
unsigned int flags
Definition: http_parser_merged.h:150
+
void * data
Definition: http_parser_merged.h:176
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/http__request_8h_source.html b/1.2/reference/http__request_8h_source.html new file mode 100644 index 000000000..b3058aeae --- /dev/null +++ b/1.2/reference/http__request_8h_source.html @@ -0,0 +1,234 @@ + + + + + + + + Crow: include/crow/http_request.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
http_request.h
+
+
+
1 #pragma once
+
2 
+
3 #ifdef CROW_USE_BOOST
+
4 #include <boost/asio.hpp>
+
5 #else
+
6 #ifndef ASIO_STANDALONE
+
7 #define ASIO_STANDALONE
+
8 #endif
+
9 #include <asio.hpp>
+
10 #endif
+
11 
+
12 #include "crow/common.h"
+
13 #include "crow/ci_map.h"
+
14 #include "crow/query_string.h"
+
15 
+
16 namespace crow // NOTE: Already documented in "crow/app.h"
+
17 {
+
18 #ifdef CROW_USE_BOOST
+
19  namespace asio = boost::asio;
+
20 #endif
+
21 
+
22  /// Find and return the value associated with the key. (returns an empty string if nothing is found)
+
23  template<typename T>
+
24  inline const std::string& get_header_value(const T& headers, const std::string& key)
+
25  {
+
26  if (headers.count(key))
+
27  {
+
28  return headers.find(key)->second;
+
29  }
+
30  static std::string empty;
+
31  return empty;
+
32  }
+
33 
+
34  /// An HTTP request.
+
35  struct request
+
36  {
+
37  HTTPMethod method;
+
38  std::string raw_url; ///< The full URL containing the `?` and URL parameters.
+
39  std::string url; ///< The endpoint without any parameters.
+
40  query_string url_params; ///< The parameters associated with the request. (everything after the `?` in the URL)
+
41  ci_map headers;
+
42  std::string body;
+
43  std::string remote_ip_address; ///< The IP address from which the request was sent.
+
44  unsigned char http_ver_major, http_ver_minor;
+
45  bool keep_alive, ///< Whether or not the server should send a `connection: Keep-Alive` header to the client.
+
46  close_connection, ///< Whether or not the server should shut down the TCP connection once a response is sent.
+
47  upgrade; ///< Whether or noth the server should change the HTTP connection to a different connection.
+
48 
+
49  void* middleware_context{};
+
50  void* middleware_container{};
+
51  asio::io_service* io_service{};
+
52 
+
53  /// Construct an empty request. (sets the method to `GET`)
+ +
55  method(HTTPMethod::Get)
+
56  {}
+
57 
+
58  /// Construct a request with all values assigned.
+
59  request(HTTPMethod method, std::string raw_url, std::string url, query_string url_params, ci_map headers, std::string body, unsigned char http_major, unsigned char http_minor, bool has_keep_alive, bool has_close_connection, bool is_upgrade):
+
60  method(method), raw_url(std::move(raw_url)), url(std::move(url)), url_params(std::move(url_params)), headers(std::move(headers)), body(std::move(body)), http_ver_major(http_major), http_ver_minor(http_minor), keep_alive(has_keep_alive), close_connection(has_close_connection), upgrade(is_upgrade)
+
61  {}
+
62 
+
63  void add_header(std::string key, std::string value)
+
64  {
+
65  headers.emplace(std::move(key), std::move(value));
+
66  }
+
67 
+
68  const std::string& get_header_value(const std::string& key) const
+
69  {
+
70  return crow::get_header_value(headers, key);
+
71  }
+
72 
+
73  bool check_version(unsigned char major, unsigned char minor) const
+
74  {
+
75  return http_ver_major == major && http_ver_minor == minor;
+
76  }
+
77 
+
78  /// Get the body as parameters in QS format.
+
79 
+
80  ///
+
81  /// This is meant to be used with requests of type "application/x-www-form-urlencoded"
+ +
83  {
+
84  return query_string(body, false);
+
85  }
+
86 
+
87  /// Send data to whoever made this request with a completion handler and return immediately.
+
88  template<typename CompletionHandler>
+
89  void post(CompletionHandler handler)
+
90  {
+
91  io_service->post(handler);
+
92  }
+
93 
+
94  /// Send data to whoever made this request with a completion handler.
+
95  template<typename CompletionHandler>
+
96  void dispatch(CompletionHandler handler)
+
97  {
+
98  io_service->dispatch(handler);
+
99  }
+
100  };
+
101 } // namespace crow
+
A class to represent any data coming after the ? in the request URL into key-value pairs.
Definition: query_string.h:294
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
const std::string & get_header_value(const T &headers, const std::string &key)
Find and return the value associated with the key. (returns an empty string if nothing is found)
Definition: http_request.h:24
+
An HTTP request.
Definition: http_request.h:36
+
request(HTTPMethod method, std::string raw_url, std::string url, query_string url_params, ci_map headers, std::string body, unsigned char http_major, unsigned char http_minor, bool has_keep_alive, bool has_close_connection, bool is_upgrade)
Construct a request with all values assigned.
Definition: http_request.h:59
+
void post(CompletionHandler handler)
Send data to whoever made this request with a completion handler and return immediately.
Definition: http_request.h:89
+
bool close_connection
Whether or not the server should shut down the TCP connection once a response is sent.
Definition: http_request.h:46
+
bool keep_alive
Whether or not the server should send a connection: Keep-Alive header to the client.
Definition: http_request.h:45
+
std::string raw_url
The full URL containing the ? and URL parameters.
Definition: http_request.h:38
+
query_string url_params
The parameters associated with the request. (everything after the ? in the URL)
Definition: http_request.h:40
+
request()
Construct an empty request. (sets the method to GET)
Definition: http_request.h:54
+
std::string url
The endpoint without any parameters.
Definition: http_request.h:39
+
std::string remote_ip_address
The IP address from which the request was sent.
Definition: http_request.h:43
+
void dispatch(CompletionHandler handler)
Send data to whoever made this request with a completion handler.
Definition: http_request.h:96
+
bool upgrade
Whether or noth the server should change the HTTP connection to a different connection.
Definition: http_request.h:47
+
const query_string get_body_params() const
Get the body as parameters in QS format.
Definition: http_request.h:82
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/http__response_8h_source.html b/1.2/reference/http__response_8h_source.html new file mode 100644 index 000000000..6737c593a --- /dev/null +++ b/1.2/reference/http__response_8h_source.html @@ -0,0 +1,469 @@ + + + + + + + + Crow: include/crow/http_response.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
http_response.h
+
+
+
1 #pragma once
+
2 #include <string>
+
3 #include <unordered_map>
+
4 #include <ios>
+
5 #include <fstream>
+
6 #include <sstream>
+
7 // S_ISREG is not defined for windows
+
8 // This defines it like suggested in https://stackoverflow.com/a/62371749
+
9 #if defined(_MSC_VER)
+
10 #define _CRT_INTERNAL_NONSTDC_NAMES 1
+
11 #endif
+
12 #include <sys/stat.h>
+
13 #if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
+
14 #define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
+
15 #endif
+
16 
+
17 #include "crow/http_request.h"
+
18 #include "crow/ci_map.h"
+
19 #include "crow/socket_adaptors.h"
+
20 #include "crow/logging.h"
+
21 #include "crow/mime_types.h"
+
22 #include "crow/returnable.h"
+
23 
+
24 
+
25 namespace crow
+
26 {
+
27  template<typename Adaptor, typename Handler, typename... Middlewares>
+
28  class Connection;
+
29 
+
30  class Router;
+
31 
+
32  /// HTTP response
+
33  struct response
+
34  {
+
35  template<typename Adaptor, typename Handler, typename... Middlewares>
+
36  friend class crow::Connection;
+
37 
+
38  friend class Router;
+
39 
+
40  int code{200}; ///< The Status code for the response.
+
41  std::string body; ///< The actual payload containing the response data.
+
42  ci_map headers; ///< HTTP headers.
+
43 
+
44 #ifdef CROW_ENABLE_COMPRESSION
+
45  bool compressed = true; ///< If compression is enabled and this is false, the individual response will not be compressed.
+
46 #endif
+
47  bool skip_body = false; ///< Whether this is a response to a HEAD request.
+
48  bool manual_length_header = false; ///< Whether Crow should automatically add a "Content-Length" header.
+
49 
+
50  /// Set the value of an existing header in the response.
+
51  void set_header(std::string key, std::string value)
+
52  {
+
53  headers.erase(key);
+
54  headers.emplace(std::move(key), std::move(value));
+
55  }
+
56 
+
57  /// Add a new header to the response.
+
58  void add_header(std::string key, std::string value)
+
59  {
+
60  headers.emplace(std::move(key), std::move(value));
+
61  }
+
62 
+
63  const std::string& get_header_value(const std::string& key)
+
64  {
+
65  return crow::get_header_value(headers, key);
+
66  }
+
67 
+
68  // naive validation of a mime-type string
+
69  static bool validate_mime_type(const std::string& candidate) noexcept
+
70  {
+
71  // Here we simply check that the candidate type starts with
+
72  // a valid parent type, and has at least one character afterwards.
+
73  std::array<std::string, 10> valid_parent_types = {
+
74  "application/", "audio/", "font/", "example/",
+
75  "image/", "message/", "model/", "multipart/",
+
76  "text/", "video/"};
+
77  for (const std::string& parent : valid_parent_types)
+
78  {
+
79  // ensure the candidate is *longer* than the parent,
+
80  // to avoid unnecessary string comparison and to
+
81  // reject zero-length subtypes.
+
82  if (candidate.size() <= parent.size())
+
83  {
+
84  continue;
+
85  }
+
86  // strncmp is used rather than substr to avoid allocation,
+
87  // but a string_view approach would be better if Crow
+
88  // migrates to C++17.
+
89  if (strncmp(parent.c_str(), candidate.c_str(), parent.size()) == 0)
+
90  {
+
91  return true;
+
92  }
+
93  }
+
94  return false;
+
95  }
+
96 
+
97  // Find the mime type from the content type either by lookup,
+
98  // or by the content type itself, if it is a valid a mime type.
+
99  // Defaults to text/plain.
+
100  static std::string get_mime_type(const std::string& contentType)
+
101  {
+
102  const auto mimeTypeIterator = mime_types.find(contentType);
+
103  if (mimeTypeIterator != mime_types.end())
+
104  {
+
105  return mimeTypeIterator->second;
+
106  }
+
107  else if (validate_mime_type(contentType))
+
108  {
+
109  return contentType;
+
110  }
+
111  else
+
112  {
+
113  CROW_LOG_WARNING << "Unable to interpret mime type for content type '" << contentType << "'. Defaulting to text/plain.";
+
114  return "text/plain";
+
115  }
+
116  }
+
117 
+
118 
+
119  // clang-format off
+
120  response() {}
+
121  explicit response(int code) : code(code) {}
+
122  response(std::string body) : body(std::move(body)) {}
+
123  response(int code, std::string body) : code(code), body(std::move(body)) {}
+
124  // clang-format on
+
125  response(returnable&& value)
+
126  {
+
127  body = value.dump();
+
128  set_header("Content-Type", value.content_type);
+
129  }
+
130  response(returnable& value)
+
131  {
+
132  body = value.dump();
+
133  set_header("Content-Type", value.content_type);
+
134  }
+
135  response(int code, returnable& value):
+
136  code(code)
+
137  {
+
138  body = value.dump();
+
139  set_header("Content-Type", value.content_type);
+
140  }
+
141  response(int code, returnable&& value):
+
142  code(code), body(value.dump())
+
143  {
+
144  set_header("Content-Type", std::move(value.content_type));
+
145  }
+
146 
+
147  response(response&& r)
+
148  {
+
149  *this = std::move(r);
+
150  }
+
151 
+
152  response(std::string contentType, std::string body):
+
153  body(std::move(body))
+
154  {
+
155  set_header("Content-Type", get_mime_type(contentType));
+
156  }
+
157 
+
158  response(int code, std::string contentType, std::string body):
+
159  code(code), body(std::move(body))
+
160  {
+
161  set_header("Content-Type", get_mime_type(contentType));
+
162  }
+
163 
+
164  response& operator=(const response& r) = delete;
+
165 
+
166  response& operator=(response&& r) noexcept
+
167  {
+
168  body = std::move(r.body);
+
169  code = r.code;
+
170  headers = std::move(r.headers);
+
171  completed_ = r.completed_;
+
172  file_info = std::move(r.file_info);
+
173  return *this;
+
174  }
+
175 
+
176  /// Check if the response has completed (whether response.end() has been called)
+
177  bool is_completed() const noexcept
+
178  {
+
179  return completed_;
+
180  }
+
181 
+
182  void clear()
+
183  {
+
184  body.clear();
+
185  code = 200;
+
186  headers.clear();
+
187  completed_ = false;
+
188  file_info = static_file_info{};
+
189  }
+
190 
+
191  /// Return a "Temporary Redirect" response.
+
192 
+
193  ///
+
194  /// Location can either be a route or a full URL.
+
195  void redirect(const std::string& location)
+
196  {
+
197  code = 307;
+
198  set_header("Location", location);
+
199  }
+
200 
+
201  /// Return a "Permanent Redirect" response.
+
202 
+
203  ///
+
204  /// Location can either be a route or a full URL.
+
205  void redirect_perm(const std::string& location)
+
206  {
+
207  code = 308;
+
208  set_header("Location", location);
+
209  }
+
210 
+
211  /// Return a "Found (Moved Temporarily)" response.
+
212 
+
213  ///
+
214  /// Location can either be a route or a full URL.
+
215  void moved(const std::string& location)
+
216  {
+
217  code = 302;
+
218  set_header("Location", location);
+
219  }
+
220 
+
221  /// Return a "Moved Permanently" response.
+
222 
+
223  ///
+
224  /// Location can either be a route or a full URL.
+
225  void moved_perm(const std::string& location)
+
226  {
+
227  code = 301;
+
228  set_header("Location", location);
+
229  }
+
230 
+
231  void write(const std::string& body_part)
+
232  {
+
233  body += body_part;
+
234  }
+
235 
+
236  /// Set the response completion flag and call the handler (to send the response).
+
237  void end()
+
238  {
+
239  if (!completed_)
+
240  {
+
241  completed_ = true;
+
242  if (skip_body)
+
243  {
+
244  set_header("Content-Length", std::to_string(body.size()));
+
245  body = "";
+
246  manual_length_header = true;
+
247  }
+
248  if (complete_request_handler_)
+
249  {
+
250  complete_request_handler_();
+
251  manual_length_header = false;
+
252  skip_body = false;
+
253  }
+
254  }
+
255  }
+
256 
+
257  /// Same as end() except it adds a body part right before ending.
+
258  void end(const std::string& body_part)
+
259  {
+
260  body += body_part;
+
261  end();
+
262  }
+
263 
+
264  /// Check if the connection is still alive (usually by checking the socket status).
+
265  bool is_alive()
+
266  {
+
267  return is_alive_helper_ && is_alive_helper_();
+
268  }
+
269 
+
270  /// Check whether the response has a static file defined.
+ +
272  {
+
273  return file_info.path.size();
+
274  }
+
275 
+
276  /// This constains metadata (coming from the `stat` command) related to any static files associated with this response.
+
277 
+
278  ///
+
279  /// Either a static file or a string body can be returned as 1 response.
+ +
281  {
+
282  std::string path = "";
+
283  struct stat statbuf;
+
284  int statResult;
+
285  };
+
286 
+
287  /// Return a static file as the response body
+
288  void set_static_file_info(std::string path)
+
289  {
+
290  utility::sanitize_filename(path);
+ +
292  }
+
293 
+
294  /// Return a static file as the response body without sanitizing the path (use set_static_file_info instead)
+
295  void set_static_file_info_unsafe(std::string path)
+
296  {
+
297  file_info.path = path;
+
298  file_info.statResult = stat(file_info.path.c_str(), &file_info.statbuf);
+
299 #ifdef CROW_ENABLE_COMPRESSION
+
300  compressed = false;
+
301 #endif
+
302  if (file_info.statResult == 0 && S_ISREG(file_info.statbuf.st_mode))
+
303  {
+
304  std::size_t last_dot = path.find_last_of(".");
+
305  std::string extension = path.substr(last_dot + 1);
+
306  code = 200;
+
307  this->add_header("Content-Length", std::to_string(file_info.statbuf.st_size));
+
308 
+
309  if (!extension.empty())
+
310  {
+
311  this->add_header("Content-Type", get_mime_type(extension));
+
312  }
+
313  }
+
314  else
+
315  {
+
316  code = 404;
+
317  file_info.path.clear();
+
318  }
+
319  }
+
320 
+
321  private:
+
322  bool completed_{};
+
323  std::function<void()> complete_request_handler_;
+
324  std::function<bool()> is_alive_helper_;
+
325  static_file_info file_info;
+
326  };
+
327 } // namespace crow
+
An HTTP connection.
Definition: http_connection.h:48
+
Handles matching requests to existing rules and upgrade requests.
Definition: routing.h:1254
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
const std::string & get_header_value(const T &headers, const std::string &key)
Find and return the value associated with the key. (returns an empty string if nothing is found)
Definition: http_request.h:24
+
This constains metadata (coming from the stat command) related to any static files associated with th...
Definition: http_response.h:281
+
HTTP response.
Definition: http_response.h:34
+
void end(const std::string &body_part)
Same as end() except it adds a body part right before ending.
Definition: http_response.h:258
+
void add_header(std::string key, std::string value)
Add a new header to the response.
Definition: http_response.h:58
+
bool skip_body
Whether this is a response to a HEAD request.
Definition: http_response.h:47
+
void moved(const std::string &location)
Return a "Found (Moved Temporarily)" response.
Definition: http_response.h:215
+
void set_static_file_info(std::string path)
Return a static file as the response body.
Definition: http_response.h:288
+
bool manual_length_header
Whether Crow should automatically add a "Content-Length" header.
Definition: http_response.h:48
+
void redirect_perm(const std::string &location)
Return a "Permanent Redirect" response.
Definition: http_response.h:205
+
void moved_perm(const std::string &location)
Return a "Moved Permanently" response.
Definition: http_response.h:225
+
bool is_completed() const noexcept
Check if the response has completed (whether response.end() has been called)
Definition: http_response.h:177
+
int code
The Status code for the response.
Definition: http_response.h:40
+
void set_header(std::string key, std::string value)
Set the value of an existing header in the response.
Definition: http_response.h:51
+
void end()
Set the response completion flag and call the handler (to send the response).
Definition: http_response.h:237
+
void redirect(const std::string &location)
Return a "Temporary Redirect" response.
Definition: http_response.h:195
+
bool is_alive()
Check if the connection is still alive (usually by checking the socket status).
Definition: http_response.h:265
+
void set_static_file_info_unsafe(std::string path)
Return a static file as the response body without sanitizing the path (use set_static_file_info inste...
Definition: http_response.h:295
+
ci_map headers
HTTP headers.
Definition: http_response.h:42
+
std::string body
The actual payload containing the response data.
Definition: http_response.h:41
+
bool compressed
If compression is enabled and this is false, the individual response will not be compressed.
Definition: http_response.h:45
+
bool is_static_type()
Check whether the response has a static file defined.
Definition: http_response.h:271
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/http__server_8h_source.html b/1.2/reference/http__server_8h_source.html new file mode 100644 index 000000000..d85dc2b79 --- /dev/null +++ b/1.2/reference/http__server_8h_source.html @@ -0,0 +1,422 @@ + + + + + + + + Crow: include/crow/http_server.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
http_server.h
+
+
+
1 #pragma once
+
2 
+
3 #ifdef CROW_USE_BOOST
+
4 #include <boost/asio.hpp>
+
5 #ifdef CROW_ENABLE_SSL
+
6 #include <boost/asio/ssl.hpp>
+
7 #endif
+
8 #else
+
9 #ifndef ASIO_STANDALONE
+
10 #define ASIO_STANDALONE
+
11 #endif
+
12 #include <asio.hpp>
+
13 #ifdef CROW_ENABLE_SSL
+
14 #include <asio/ssl.hpp>
+
15 #endif
+
16 #endif
+
17 
+
18 #include <atomic>
+
19 #include <chrono>
+
20 #include <cstdint>
+
21 #include <future>
+
22 #include <memory>
+
23 #include <vector>
+
24 
+
25 #include "crow/version.h"
+
26 #include "crow/http_connection.h"
+
27 #include "crow/logging.h"
+
28 #include "crow/task_timer.h"
+
29 
+
30 
+
31 namespace crow // NOTE: Already documented in "crow/app.h"
+
32 {
+
33 #ifdef CROW_USE_BOOST
+
34  namespace asio = boost::asio;
+
35  using error_code = boost::system::error_code;
+
36 #else
+
37  using error_code = asio::error_code;
+
38 #endif
+
39  using tcp = asio::ip::tcp;
+
40 
+
41  template<typename Handler, typename Adaptor = SocketAdaptor, typename... Middlewares>
+
42  class Server
+
43  {
+
44  public:
+
45  Server(Handler* handler, std::string bindaddr, uint16_t port, std::string server_name = std::string("Crow/") + VERSION, std::tuple<Middlewares...>* middlewares = nullptr, uint16_t concurrency = 1, uint8_t timeout = 5, typename Adaptor::context* adaptor_ctx = nullptr):
+
46  acceptor_(io_service_, tcp::endpoint(asio::ip::address::from_string(bindaddr), port)),
+
47  signals_(io_service_),
+
48  tick_timer_(io_service_),
+
49  handler_(handler),
+
50  concurrency_(concurrency),
+
51  timeout_(timeout),
+
52  server_name_(server_name),
+
53  port_(port),
+
54  bindaddr_(bindaddr),
+
55  task_queue_length_pool_(concurrency_ - 1),
+
56  middlewares_(middlewares),
+
57  adaptor_ctx_(adaptor_ctx)
+
58  {}
+
59 
+
60  void set_tick_function(std::chrono::milliseconds d, std::function<void()> f)
+
61  {
+
62  tick_interval_ = d;
+
63  tick_function_ = f;
+
64  }
+
65 
+
66  void on_tick()
+
67  {
+
68  tick_function_();
+
69  tick_timer_.expires_after(std::chrono::milliseconds(tick_interval_.count()));
+
70  tick_timer_.async_wait([this](const error_code& ec) {
+
71  if (ec)
+
72  return;
+
73  on_tick();
+
74  });
+
75  }
+
76 
+
77  void run()
+
78  {
+
79  uint16_t worker_thread_count = concurrency_ - 1;
+
80  for (int i = 0; i < worker_thread_count; i++)
+
81  io_service_pool_.emplace_back(new asio::io_service());
+
82  get_cached_date_str_pool_.resize(worker_thread_count);
+
83  task_timer_pool_.resize(worker_thread_count);
+
84 
+
85  std::vector<std::future<void>> v;
+
86  std::atomic<int> init_count(0);
+
87  for (uint16_t i = 0; i < worker_thread_count; i++)
+
88  v.push_back(
+
89  std::async(
+
90  std::launch::async, [this, i, &init_count] {
+
91  // thread local date string get function
+
92  auto last = std::chrono::steady_clock::now();
+
93 
+
94  std::string date_str;
+
95  auto update_date_str = [&] {
+
96  auto last_time_t = time(0);
+
97  tm my_tm;
+
98 
+
99 #if defined(_MSC_VER) || defined(__MINGW32__)
+
100  gmtime_s(&my_tm, &last_time_t);
+
101 #else
+
102  gmtime_r(&last_time_t, &my_tm);
+
103 #endif
+
104  date_str.resize(100);
+
105  size_t date_str_sz = strftime(&date_str[0], 99, "%a, %d %b %Y %H:%M:%S GMT", &my_tm);
+
106  date_str.resize(date_str_sz);
+
107  };
+
108  update_date_str();
+
109  get_cached_date_str_pool_[i] = [&]() -> std::string {
+
110  if (std::chrono::steady_clock::now() - last >= std::chrono::seconds(1))
+
111  {
+
112  last = std::chrono::steady_clock::now();
+
113  update_date_str();
+
114  }
+
115  return date_str;
+
116  };
+
117 
+
118  // initializing task timers
+
119  detail::task_timer task_timer(*io_service_pool_[i]);
+
120  task_timer.set_default_timeout(timeout_);
+
121  task_timer_pool_[i] = &task_timer;
+
122  task_queue_length_pool_[i] = 0;
+
123 
+
124  init_count++;
+
125  while (1)
+
126  {
+
127  try
+
128  {
+
129  if (io_service_pool_[i]->run() == 0)
+
130  {
+
131  // when io_service.run returns 0, there are no more works to do.
+
132  break;
+
133  }
+
134  }
+
135  catch (std::exception& e)
+
136  {
+
137  CROW_LOG_ERROR << "Worker Crash: An uncaught exception occurred: " << e.what();
+
138  }
+
139  }
+
140  }));
+
141 
+
142  if (tick_function_ && tick_interval_.count() > 0)
+
143  {
+
144  tick_timer_.expires_after(std::chrono::milliseconds(tick_interval_.count()));
+
145  tick_timer_.async_wait(
+
146  [this](const error_code& ec) {
+
147  if (ec)
+
148  return;
+
149  on_tick();
+
150  });
+
151  }
+
152 
+
153  port_ = acceptor_.local_endpoint().port();
+
154  handler_->port(port_);
+
155 
+
156 
+
157  CROW_LOG_INFO << server_name_ << " server is running at " << (handler_->ssl_used() ? "https://" : "http://") << bindaddr_ << ":" << acceptor_.local_endpoint().port() << " using " << concurrency_ << " threads";
+
158  CROW_LOG_INFO << "Call `app.loglevel(crow::LogLevel::Warning)` to hide Info level logs.";
+
159 
+
160  signals_.async_wait(
+
161  [&](const error_code& /*error*/, int /*signal_number*/) {
+
162  stop();
+
163  });
+
164 
+
165  while (worker_thread_count != init_count)
+
166  std::this_thread::yield();
+
167 
+
168  do_accept();
+
169 
+
170  std::thread(
+
171  [this] {
+
172  notify_start();
+
173  io_service_.run();
+
174  CROW_LOG_INFO << "Exiting.";
+
175  })
+
176  .join();
+
177  }
+
178 
+
179  void stop()
+
180  {
+
181  shutting_down_ = true; // Prevent the acceptor from taking new connections
+
182  for (auto& io_service : io_service_pool_)
+
183  {
+
184  if (io_service != nullptr)
+
185  {
+
186  CROW_LOG_INFO << "Closing IO service " << &io_service;
+
187  io_service->stop(); // Close all io_services (and HTTP connections)
+
188  }
+
189  }
+
190 
+
191  CROW_LOG_INFO << "Closing main IO service (" << &io_service_ << ')';
+
192  io_service_.stop(); // Close main io_service
+
193  }
+
194 
+
195  /// Wait until the server has properly started
+ +
197  {
+
198  std::unique_lock<std::mutex> lock(start_mutex_);
+
199  if (!server_started_)
+
200  cv_started_.wait(lock);
+
201  }
+
202 
+
203  void signal_clear()
+
204  {
+
205  signals_.clear();
+
206  }
+
207 
+
208  void signal_add(int signal_number)
+
209  {
+
210  signals_.add(signal_number);
+
211  }
+
212 
+
213  private:
+
214  uint16_t pick_io_service_idx()
+
215  {
+
216  uint16_t min_queue_idx = 0;
+
217 
+
218  // TODO improve load balancing
+
219  // size_t is used here to avoid the security issue https://codeql.github.com/codeql-query-help/cpp/cpp-comparison-with-wider-type/
+
220  // even though the max value of this can be only uint16_t as concurrency is uint16_t.
+
221  for (size_t i = 1; i < task_queue_length_pool_.size() && task_queue_length_pool_[min_queue_idx] > 0; i++)
+
222  // No need to check other io_services if the current one has no tasks
+
223  {
+
224  if (task_queue_length_pool_[i] < task_queue_length_pool_[min_queue_idx])
+
225  min_queue_idx = i;
+
226  }
+
227  return min_queue_idx;
+
228  }
+
229 
+
230  void do_accept()
+
231  {
+
232  if (!shutting_down_)
+
233  {
+
234  uint16_t service_idx = pick_io_service_idx();
+
235  asio::io_service& is = *io_service_pool_[service_idx];
+
236  task_queue_length_pool_[service_idx]++;
+
237  CROW_LOG_DEBUG << &is << " {" << service_idx << "} queue length: " << task_queue_length_pool_[service_idx];
+
238 
+
239  auto p = std::make_shared<Connection<Adaptor, Handler, Middlewares...>>(
+
240  is, handler_, server_name_, middlewares_,
+
241  get_cached_date_str_pool_[service_idx], *task_timer_pool_[service_idx], adaptor_ctx_, task_queue_length_pool_[service_idx]);
+
242 
+
243  acceptor_.async_accept(
+
244  p->socket(),
+
245  [this, p, &is, service_idx](error_code ec) {
+
246  if (!ec)
+
247  {
+
248  is.post(
+
249  [p] {
+
250  p->start();
+
251  });
+
252  }
+
253  else
+
254  {
+
255  task_queue_length_pool_[service_idx]--;
+
256  CROW_LOG_DEBUG << &is << " {" << service_idx << "} queue length: " << task_queue_length_pool_[service_idx];
+
257  }
+
258  do_accept();
+
259  });
+
260  }
+
261  }
+
262 
+
263  /// Notify anything using `wait_for_start()` to proceed
+
264  void notify_start()
+
265  {
+
266  std::unique_lock<std::mutex> lock(start_mutex_);
+
267  server_started_ = true;
+
268  cv_started_.notify_all();
+
269  }
+
270 
+
271  private:
+
272  std::vector<std::unique_ptr<asio::io_service>> io_service_pool_;
+
273  asio::io_service io_service_;
+
274  std::vector<detail::task_timer*> task_timer_pool_;
+
275  std::vector<std::function<std::string()>> get_cached_date_str_pool_;
+
276  tcp::acceptor acceptor_;
+
277  bool shutting_down_ = false;
+
278  bool server_started_{false};
+
279  std::condition_variable cv_started_;
+
280  std::mutex start_mutex_;
+
281  asio::signal_set signals_;
+
282 
+
283  asio::basic_waitable_timer<std::chrono::high_resolution_clock> tick_timer_;
+
284 
+
285  Handler* handler_;
+
286  uint16_t concurrency_{2};
+
287  std::uint8_t timeout_;
+
288  std::string server_name_;
+
289  uint16_t port_;
+
290  std::string bindaddr_;
+
291  std::vector<std::atomic<unsigned int>> task_queue_length_pool_;
+
292 
+
293  std::chrono::milliseconds tick_interval_;
+
294  std::function<void()> tick_function_;
+
295 
+
296  std::tuple<Middlewares...>* middlewares_;
+
297 
+
298  typename Adaptor::context* adaptor_ctx_;
+
299  };
+
300 } // namespace crow
+
Definition: http_server.h:43
+
void wait_for_start()
Wait until the server has properly started.
Definition: http_server.h:196
+
A class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 ...
Definition: task_timer.h:34
+
void set_default_timeout(std::uint8_t timeout)
Set the default timeout for this task_timer instance. (Default: 5)
Definition: task_timer.h:98
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/index.html b/1.2/reference/index.html new file mode 100644 index 000000000..2affbd9cc --- /dev/null +++ b/1.2/reference/index.html @@ -0,0 +1,131 @@ + + + + + + + + Crow: Main Page + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ + + + + + + \ No newline at end of file diff --git a/1.2/reference/jquery.js b/1.2/reference/jquery.js new file mode 100644 index 000000000..103c32d79 --- /dev/null +++ b/1.2/reference/jquery.js @@ -0,0 +1,35 @@ +/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0a;a++)for(i in o[a])n=o[a][i],o[a].hasOwnProperty(i)&&void 0!==n&&(e[i]=t.isPlainObject(n)?t.isPlainObject(e[i])?t.widget.extend({},e[i],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,i){var n=i.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=s.call(arguments,1),h=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(h=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):h=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new i(o,this))})),h}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{classes:{},disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+o.eventNamespace,c=h[2];c?n.on(l,c,r):i.on(l,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,h=/top|center|bottom/,l=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("
"),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.widthi?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};l>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),h.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-r-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-r-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,m=-2*e.offset[1];0>c?(s=t.top+p+f+m+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+m)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+m-h,(i>0||u>a(i))&&(t.top+=p+f+m))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}}),t.ui.focusable=function(i,s){var n,o,a,r,h,l=i.nodeName.toLowerCase();return"area"===l?(n=i.parentNode,o=n.name,i.href&&o&&"map"===n.nodeName.toLowerCase()?(a=t("img[usemap='#"+o+"']"),a.length>0&&a.is(":visible")):!1):(/^(input|select|textarea|button|object)$/.test(l)?(r=!i.disabled,r&&(h=t(i).closest("fieldset")[0],h&&(r=!h.disabled))):r="a"===l?i.href||s:s,r&&t(i).is(":visible")&&e(t(i)))},t.extend(t.expr[":"],{focusable:function(e){return t.ui.focusable(e,null!=t.attr(e,"tabindex"))}}),t.ui.focusable,t.fn.form=function(){return"string"==typeof this[0].form?this.closest("form"):t(this[0].form)},t.ui.formResetMixin={_formResetHandler:function(){var e=t(this);setTimeout(function(){var i=e.data("ui-form-reset-instances");t.each(i,function(){this.refresh()})})},_bindFormResetHandler:function(){if(this.form=this.element.form(),this.form.length){var t=this.form.data("ui-form-reset-instances")||[];t.length||this.form.on("reset.ui-form-reset",this._formResetHandler),t.push(this),this.form.data("ui-form-reset-instances",t)}},_unbindFormResetHandler:function(){if(this.form.length){var e=this.form.data("ui-form-reset-instances");e.splice(t.inArray(this,e),1),e.length?this.form.data("ui-form-reset-instances",e):this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset")}}},"1.7"===t.fn.jquery.substring(0,3)&&(t.each(["Width","Height"],function(e,i){function s(e,i,s,o){return t.each(n,function(){i-=parseFloat(t.css(e,"padding"+this))||0,s&&(i-=parseFloat(t.css(e,"border"+this+"Width"))||0),o&&(i-=parseFloat(t.css(e,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],o=i.toLowerCase(),a={innerWidth:t.fn.innerWidth,innerHeight:t.fn.innerHeight,outerWidth:t.fn.outerWidth,outerHeight:t.fn.outerHeight};t.fn["inner"+i]=function(e){return void 0===e?a["inner"+i].call(this):this.each(function(){t(this).css(o,s(this,e)+"px")})},t.fn["outer"+i]=function(e,n){return"number"!=typeof e?a["outer"+i].call(this,e):this.each(function(){t(this).css(o,s(this,e,!0,n)+"px")})}}),t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.ui.escapeSelector=function(){var t=/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;return function(e){return e.replace(t,"\\$1")}}(),t.fn.labels=function(){var e,i,s,n,o;return this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(n=this.eq(0).parents("label"),s=this.attr("id"),s&&(e=this.eq(0).parents().last(),o=e.add(e.length?e.siblings():this.siblings()),i="label[for='"+t.ui.escapeSelector(s)+"']",n=n.add(o.find(i).addBack(i))),this.pushStack(n))},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.extend(t.expr[":"],{tabbable:function(e){var i=t.attr(e,"tabindex"),s=null!=i;return(!s||i>=0)&&t.ui.focusable(e,s)}}),t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var n=!1;t(document).on("mouseup",function(){n=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!n){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,s=1===e.which,o="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return s&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),n=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,n=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.widget("ui.resizable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("
").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("
"),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,h=this._change[o];return this._updatePrevProperties(),h?(i=h.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,h=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(a,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidth=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidtht.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,h=this.originalPosition.top+this.originalSize.height,l=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&l&&(t.left=r-e.minWidth),s&&l&&(t.left=r-e.maxWidth),a&&c&&(t.top=h-e.minHeight),n&&c&&(t.top=h-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("
"),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element +},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-a},l=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,h=t(this).resizable("instance"),l=h.options,c=h.element,u=l.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(h.containerElement=t(d),/document/.test(u)||u===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=h._num(e.css("padding"+s))}),h.containerOffset=e.offset(),h.containerPosition=e.position(),h.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,o=h.containerSize.width,a=h._hasScroll(d,"left")?d.scrollWidth:o,r=h._hasScroll(d)?d.scrollHeight:n,h.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,h=a.containerOffset,l=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(a._helper?h.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-h.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?h.left:0),l.top<(a._helper?h.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-h.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?h.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-h.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-h.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.width,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),h=a.outerWidth()-e.sizeDiff.width,l=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0};t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,c=h[1]||1,u=Math.round((n.width-o.width)/l)*l,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=h,_&&(p+=l),v&&(f+=c),m&&(p-=l),g&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-l)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-l>0?(i.size.width=p,i.position.left=a.left-u):(p=l-e.width,i.size.width=p,i.position.left=a.left+o.width-p))}}),t.ui.resizable});/** + * Copyright (c) 2007 Ariel Flesler - aflesler ○ gmail • com | https://github.com/flesler + * Licensed under MIT + * @author Ariel Flesler + * @version 2.1.2 + */ +;(function(f){"use strict";"function"===typeof define&&define.amd?define(["jquery"],f):"undefined"!==typeof module&&module.exports?module.exports=f(require("jquery")):f(jQuery)})(function($){"use strict";function n(a){return!a.nodeName||-1!==$.inArray(a.nodeName.toLowerCase(),["iframe","#document","html","body"])}function h(a){return $.isFunction(a)||$.isPlainObject(a)?a:{top:a,left:a}}var p=$.scrollTo=function(a,d,b){return $(window).scrollTo(a,d,b)};p.defaults={axis:"xy",duration:0,limit:!0};$.fn.scrollTo=function(a,d,b){"object"=== typeof d&&(b=d,d=0);"function"===typeof b&&(b={onAfter:b});"max"===a&&(a=9E9);b=$.extend({},p.defaults,b);d=d||b.duration;var u=b.queue&&1=f[g]?0:Math.min(f[g],n));!a&&1-1){targetElements.on(evt+EVENT_NAMESPACE,function elementToggle(event){$.powerTip.toggle(this,event)})}else{targetElements.on(evt+EVENT_NAMESPACE,function elementOpen(event){$.powerTip.show(this,event)})}});$.each(options.closeEvents,function(idx,evt){if($.inArray(evt,options.openEvents)<0){targetElements.on(evt+EVENT_NAMESPACE,function elementClose(event){$.powerTip.hide(this,!isMouseEvent(event))})}});targetElements.on("keydown"+EVENT_NAMESPACE,function elementKeyDown(event){if(event.keyCode===27){$.powerTip.hide(this,true)}})}return targetElements};$.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]};$.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};$.powerTip={show:function apiShowTip(element,event){if(isMouseEvent(event)){trackMouse(event);session.previousX=event.pageX;session.previousY=event.pageY;$(element).data(DATA_DISPLAYCONTROLLER).show()}else{$(element).first().data(DATA_DISPLAYCONTROLLER).show(true,true)}return element},reposition:function apiResetPosition(element){$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();return element},hide:function apiCloseTip(element,immediate){var displayController;immediate=element?immediate:true;if(element){displayController=$(element).first().data(DATA_DISPLAYCONTROLLER)}else if(session.activeHover){displayController=session.activeHover.data(DATA_DISPLAYCONTROLLER)}if(displayController){displayController.hide(immediate)}return element},toggle:function apiToggle(element,event){if(session.activeHover&&session.activeHover.is(element)){$.powerTip.hide(element,!isMouseEvent(event))}else{$.powerTip.show(element,event)}return element}};$.powerTip.showTip=$.powerTip.show;$.powerTip.closeTip=$.powerTip.hide;function CSSCoordinates(){var me=this;me.top="auto";me.left="auto";me.right="auto";me.bottom="auto";me.set=function(property,value){if($.isNumeric(value)){me[property]=Math.round(value)}}}function DisplayController(element,options,tipController){var hoverTimer=null,myCloseDelay=null;function openTooltip(immediate,forceOpen){cancelTimer();if(!element.data(DATA_HASACTIVEHOVER)){if(!immediate){session.tipOpenImminent=true;hoverTimer=setTimeout(function intentDelay(){hoverTimer=null;checkForIntent()},options.intentPollInterval)}else{if(forceOpen){element.data(DATA_FORCEDOPEN,true)}closeAnyDelayed();tipController.showTip(element)}}else{cancelClose()}}function closeTooltip(disableDelay){if(myCloseDelay){myCloseDelay=session.closeDelayTimeout=clearTimeout(myCloseDelay);session.delayInProgress=false}cancelTimer();session.tipOpenImminent=false;if(element.data(DATA_HASACTIVEHOVER)){element.data(DATA_FORCEDOPEN,false);if(!disableDelay){session.delayInProgress=true;session.closeDelayTimeout=setTimeout(function closeDelay(){session.closeDelayTimeout=null;tipController.hideTip(element);session.delayInProgress=false;myCloseDelay=null},options.closeDelay);myCloseDelay=session.closeDelayTimeout}else{tipController.hideTip(element)}}}function checkForIntent(){var xDifference=Math.abs(session.previousX-session.currentX),yDifference=Math.abs(session.previousY-session.currentY),totalDifference=xDifference+yDifference;if(totalDifference",{id:options.popupId});if($body.length===0){$body=$("body")}$body.append(tipElement);session.tooltips=session.tooltips?session.tooltips.add(tipElement):tipElement}if(options.followMouse){if(!tipElement.data(DATA_HASMOUSEMOVE)){$document.on("mousemove"+EVENT_NAMESPACE,positionTipOnCursor);$window.on("scroll"+EVENT_NAMESPACE,positionTipOnCursor);tipElement.data(DATA_HASMOUSEMOVE,true)}}function beginShowTip(element){element.data(DATA_HASACTIVEHOVER,true);tipElement.queue(function queueTipInit(next){showTip(element);next()})}function showTip(element){var tipContent;if(!element.data(DATA_HASACTIVEHOVER)){return}if(session.isTipOpen){if(!session.isClosing){hideTip(session.activeHover)}tipElement.delay(100).queue(function queueTipAgain(next){showTip(element);next()});return}element.trigger("powerTipPreRender");tipContent=getTooltipContent(element);if(tipContent){tipElement.empty().append(tipContent)}else{return}element.trigger("powerTipRender");session.activeHover=element;session.isTipOpen=true;tipElement.data(DATA_MOUSEONTOTIP,options.mouseOnToPopup);tipElement.addClass(options.popupClass);if(!options.followMouse||element.data(DATA_FORCEDOPEN)){positionTipOnElement(element);session.isFixedTipOpen=true}else{positionTipOnCursor()}if(!element.data(DATA_FORCEDOPEN)&&!options.followMouse){$document.on("click"+EVENT_NAMESPACE,function documentClick(event){var target=event.target;if(target!==element[0]){if(options.mouseOnToPopup){if(target!==tipElement[0]&&!$.contains(tipElement[0],target)){$.powerTip.hide()}}else{$.powerTip.hide()}}})}if(options.mouseOnToPopup&&!options.manual){tipElement.on("mouseenter"+EVENT_NAMESPACE,function tipMouseEnter(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel()}});tipElement.on("mouseleave"+EVENT_NAMESPACE,function tipMouseLeave(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide()}})}tipElement.fadeIn(options.fadeInTime,function fadeInCallback(){if(!session.desyncTimeout){session.desyncTimeout=setInterval(closeDesyncedTip,500)}element.trigger("powerTipOpen")})}function hideTip(element){session.isClosing=true;session.isTipOpen=false;session.desyncTimeout=clearInterval(session.desyncTimeout);element.data(DATA_HASACTIVEHOVER,false);element.data(DATA_FORCEDOPEN,false);$document.off("click"+EVENT_NAMESPACE);tipElement.off(EVENT_NAMESPACE);tipElement.fadeOut(options.fadeOutTime,function fadeOutCallback(){var coords=new CSSCoordinates;session.activeHover=null;session.isClosing=false;session.isFixedTipOpen=false;tipElement.removeClass();coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);tipElement.css(coords);element.trigger("powerTipClose")})}function positionTipOnCursor(){var tipWidth,tipHeight,coords,collisions,collisionCount;if(!session.isFixedTipOpen&&(session.isTipOpen||session.tipOpenImminent&&tipElement.data(DATA_HASMOUSEMOVE))){tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=new CSSCoordinates;coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);collisions=getViewportCollisions(coords,tipWidth,tipHeight);if(collisions!==Collision.none){collisionCount=countFlags(collisions);if(collisionCount===1){if(collisions===Collision.right){coords.set("left",session.scrollLeft+session.windowWidth-tipWidth)}else if(collisions===Collision.bottom){coords.set("top",session.scrollTop+session.windowHeight-tipHeight)}}else{coords.set("left",session.currentX-tipWidth-options.offset);coords.set("top",session.currentY-tipHeight-options.offset)}}tipElement.css(coords)}}function positionTipOnElement(element){var priorityList,finalPlacement;if(options.smartPlacement||options.followMouse&&element.data(DATA_FORCEDOPEN)){priorityList=$.fn.powerTip.smartPlacementLists[options.placement];$.each(priorityList,function(idx,pos){var collisions=getViewportCollisions(placeTooltip(element,pos),tipElement.outerWidth(),tipElement.outerHeight());finalPlacement=pos;return collisions!==Collision.none})}else{placeTooltip(element,options.placement);finalPlacement=options.placement}tipElement.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt");tipElement.addClass(finalPlacement)}function placeTooltip(element,placement){var iterationCount=0,tipWidth,tipHeight,coords=new CSSCoordinates;coords.set("top",0);coords.set("left",0);tipElement.css(coords);do{tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=placementCalculator.compute(element,placement,tipWidth,tipHeight,options.offset);tipElement.css(coords)}while(++iterationCount<=5&&(tipWidth!==tipElement.outerWidth()||tipHeight!==tipElement.outerHeight()));return coords}function closeDesyncedTip(){var isDesynced=false,hasDesyncableCloseEvent=$.grep(["mouseleave","mouseout","blur","focusout"],function(eventType){return $.inArray(eventType,options.closeEvents)!==-1}).length>0;if(session.isTipOpen&&!session.isClosing&&!session.delayInProgress&&hasDesyncableCloseEvent){if(session.activeHover.data(DATA_HASACTIVEHOVER)===false||session.activeHover.is(":disabled")){isDesynced=true}else if(!isMouseOver(session.activeHover)&&!session.activeHover.is(":focus")&&!session.activeHover.data(DATA_FORCEDOPEN)){if(tipElement.data(DATA_MOUSEONTOTIP)){if(!isMouseOver(tipElement)){isDesynced=true}}else{isDesynced=true}}if(isDesynced){hideTip(session.activeHover)}}}this.showTip=beginShowTip;this.hideTip=hideTip;this.resetPosition=positionTipOnElement}function isSvgElement(element){return Boolean(window.SVGElement&&element[0]instanceof SVGElement)}function isMouseEvent(event){return Boolean(event&&$.inArray(event.type,MOUSE_EVENTS)>-1&&typeof event.pageX==="number")}function initTracking(){if(!session.mouseTrackingActive){session.mouseTrackingActive=true;getViewportDimensions();$(getViewportDimensions);$document.on("mousemove"+EVENT_NAMESPACE,trackMouse);$window.on("resize"+EVENT_NAMESPACE,trackResize);$window.on("scroll"+EVENT_NAMESPACE,trackScroll)}}function getViewportDimensions(){session.scrollLeft=$window.scrollLeft();session.scrollTop=$window.scrollTop();session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackResize(){session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackScroll(){var x=$window.scrollLeft(),y=$window.scrollTop();if(x!==session.scrollLeft){session.currentX+=x-session.scrollLeft;session.scrollLeft=x}if(y!==session.scrollTop){session.currentY+=y-session.scrollTop;session.scrollTop=y}}function trackMouse(event){session.currentX=event.pageX;session.currentY=event.pageY}function isMouseOver(element){var elementPosition=element.offset(),elementBox=element[0].getBoundingClientRect(),elementWidth=elementBox.right-elementBox.left,elementHeight=elementBox.bottom-elementBox.top;return session.currentX>=elementPosition.left&&session.currentX<=elementPosition.left+elementWidth&&session.currentY>=elementPosition.top&&session.currentY<=elementPosition.top+elementHeight}function getTooltipContent(element){var tipText=element.data(DATA_POWERTIP),tipObject=element.data(DATA_POWERTIPJQ),tipTarget=element.data(DATA_POWERTIPTARGET),targetElement,content;if(tipText){if($.isFunction(tipText)){tipText=tipText.call(element[0])}content=tipText}else if(tipObject){if($.isFunction(tipObject)){tipObject=tipObject.call(element[0])}if(tipObject.length>0){content=tipObject.clone(true,true)}}else if(tipTarget){targetElement=$("#"+tipTarget);if(targetElement.length>0){content=targetElement.html()}}return content}function getViewportCollisions(coords,elementWidth,elementHeight){var viewportTop=session.scrollTop,viewportLeft=session.scrollLeft,viewportBottom=viewportTop+session.windowHeight,viewportRight=viewportLeft+session.windowWidth,collisions=Collision.none;if(coords.topviewportBottom||Math.abs(coords.bottom-session.windowHeight)>viewportBottom){collisions|=Collision.bottom}if(coords.leftviewportRight){collisions|=Collision.left}if(coords.left+elementWidth>viewportRight||coords.right1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);/*! SmartMenus jQuery Plugin - v1.1.0 - September 17, 2017 + * http://www.smartmenus.org/ + * Copyright Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&"object"==typeof module.exports?module.exports=t(require("jquery")):t(jQuery)})(function($){function initMouseDetection(t){var e=".smartmenus_mouse";if(mouseDetectionEnabled||t)mouseDetectionEnabled&&t&&($(document).off(e),mouseDetectionEnabled=!1);else{var i=!0,s=null,o={mousemove:function(t){var e={x:t.pageX,y:t.pageY,timeStamp:(new Date).getTime()};if(s){var o=Math.abs(s.x-e.x),a=Math.abs(s.y-e.y);if((o>0||a>0)&&2>=o&&2>=a&&300>=e.timeStamp-s.timeStamp&&(mouse=!0,i)){var n=$(t.target).closest("a");n.is("a")&&$.each(menuTrees,function(){return $.contains(this.$root[0],n[0])?(this.itemEnter({currentTarget:n[0]}),!1):void 0}),i=!1}}s=e}};o[touchEvents?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut"]=function(t){isTouchEvent(t.originalEvent)&&(mouse=!1)},$(document).on(getEventsNS(o,e)),mouseDetectionEnabled=!0}}function isTouchEvent(t){return!/^(4|mouse)$/.test(t.pointerType)}function getEventsNS(t,e){e||(e="");var i={};for(var s in t)i[s.split(" ").join(e+" ")+e]=t[s];return i}var menuTrees=[],mouse=!1,touchEvents="ontouchstart"in window,mouseDetectionEnabled=!1,requestAnimationFrame=window.requestAnimationFrame||function(t){return setTimeout(t,1e3/60)},cancelAnimationFrame=window.cancelAnimationFrame||function(t){clearTimeout(t)},canAnimate=!!$.fn.animate;return $.SmartMenus=function(t,e){this.$root=$(t),this.opts=e,this.rootId="",this.accessIdPrefix="",this.$subArrow=null,this.activatedItems=[],this.visibleSubMenus=[],this.showTimeout=0,this.hideTimeout=0,this.scrollTimeout=0,this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.idInc=0,this.$firstLink=null,this.$firstSub=null,this.disabled=!1,this.$disableOverlay=null,this.$touchScrollingSub=null,this.cssTransforms3d="perspective"in t.style||"webkitPerspective"in t.style,this.wasCollapsible=!1,this.init()},$.extend($.SmartMenus,{hideAll:function(){$.each(menuTrees,function(){this.menuHideAll()})},destroy:function(){for(;menuTrees.length;)menuTrees[0].destroy();initMouseDetection(!0)},prototype:{init:function(t){var e=this;if(!t){menuTrees.push(this),this.rootId=((new Date).getTime()+Math.random()+"").replace(/\D/g,""),this.accessIdPrefix="sm-"+this.rootId+"-",this.$root.hasClass("sm-rtl")&&(this.opts.rightToLeftSubMenus=!0);var i=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).on(getEventsNS({"mouseover focusin":$.proxy(this.rootOver,this),"mouseout focusout":$.proxy(this.rootOut,this),keydown:$.proxy(this.rootKeyDown,this)},i)).on(getEventsNS({mouseenter:$.proxy(this.itemEnter,this),mouseleave:$.proxy(this.itemLeave,this),mousedown:$.proxy(this.itemDown,this),focus:$.proxy(this.itemFocus,this),blur:$.proxy(this.itemBlur,this),click:$.proxy(this.itemClick,this)},i),"a"),i+=this.rootId,this.opts.hideOnClick&&$(document).on(getEventsNS({touchstart:$.proxy(this.docTouchStart,this),touchmove:$.proxy(this.docTouchMove,this),touchend:$.proxy(this.docTouchEnd,this),click:$.proxy(this.docClick,this)},i)),$(window).on(getEventsNS({"resize orientationchange":$.proxy(this.winResize,this)},i)),this.opts.subIndicators&&(this.$subArrow=$("").addClass("sub-arrow"),this.opts.subIndicatorsText&&this.$subArrow.html(this.opts.subIndicatorsText)),initMouseDetection()}if(this.$firstSub=this.$root.find("ul").each(function(){e.menuInit($(this))}).eq(0),this.$firstLink=this.$root.find("a").eq(0),this.opts.markCurrentItem){var s=/(index|default)\.[^#\?\/]*/i,o=/#.*/,a=window.location.href.replace(s,""),n=a.replace(o,"");this.$root.find("a").each(function(){var t=this.href.replace(s,""),i=$(this);(t==a||t==n)&&(i.addClass("current"),e.opts.markCurrentTree&&i.parentsUntil("[data-smartmenus-id]","ul").each(function(){$(this).dataSM("parent-a").addClass("current")}))})}this.wasCollapsible=this.isCollapsible()},destroy:function(t){if(!t){var e=".smartmenus";this.$root.removeData("smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").off(e),e+=this.rootId,$(document).off(e),$(window).off(e),this.opts.subIndicators&&(this.$subArrow=null)}this.menuHideAll();var i=this;this.$root.find("ul").each(function(){var t=$(this);t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.dataSM("shown-before")&&((i.opts.subMenusMinWidth||i.opts.subMenusMaxWidth)&&t.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap"),t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})),0==(t.attr("id")||"").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded"),this.$root.find("a.has-submenu").each(function(){var t=$(this);0==t.attr("id").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub"),this.opts.subIndicators&&this.$root.find("span.sub-arrow").remove(),this.opts.markCurrentItem&&this.$root.find("a.current").removeClass("current"),t||(this.$root=null,this.$firstLink=null,this.$firstSub=null,this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),menuTrees.splice($.inArray(this,menuTrees),1))},disable:function(t){if(!this.disabled){if(this.menuHideAll(),!t&&!this.opts.isPopup&&this.$root.is(":visible")){var e=this.$root.offset();this.$disableOverlay=$('
').css({position:"absolute",top:e.top,left:e.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(!0),opacity:0}).appendTo(document.body)}this.disabled=!0}},docClick:function(t){return this.$touchScrollingSub?(this.$touchScrollingSub=null,void 0):((this.visibleSubMenus.length&&!$.contains(this.$root[0],t.target)||$(t.target).closest("a").length)&&this.menuHideAll(),void 0)},docTouchEnd:function(){if(this.lastTouch){if(!(!this.visibleSubMenus.length||void 0!==this.lastTouch.x2&&this.lastTouch.x1!=this.lastTouch.x2||void 0!==this.lastTouch.y2&&this.lastTouch.y1!=this.lastTouch.y2||this.lastTouch.target&&$.contains(this.$root[0],this.lastTouch.target))){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var t=this;this.hideTimeout=setTimeout(function(){t.menuHideAll()},350)}this.lastTouch=null}},docTouchMove:function(t){if(this.lastTouch){var e=t.originalEvent.touches[0];this.lastTouch.x2=e.pageX,this.lastTouch.y2=e.pageY}},docTouchStart:function(t){var e=t.originalEvent.touches[0];this.lastTouch={x1:e.pageX,y1:e.pageY,target:e.target}},enable:function(){this.disabled&&(this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),this.disabled=!1)},getClosestMenu:function(t){for(var e=$(t).closest("ul");e.dataSM("in-mega");)e=e.parent().closest("ul");return e[0]||null},getHeight:function(t){return this.getOffset(t,!0)},getOffset:function(t,e){var i;"none"==t.css("display")&&(i={position:t[0].style.position,visibility:t[0].style.visibility},t.css({position:"absolute",visibility:"hidden"}).show());var s=t[0].getBoundingClientRect&&t[0].getBoundingClientRect(),o=s&&(e?s.height||s.bottom-s.top:s.width||s.right-s.left);return o||0===o||(o=e?t[0].offsetHeight:t[0].offsetWidth),i&&t.hide().css(i),o},getStartZIndex:function(t){var e=parseInt(this[t?"$root":"$firstSub"].css("z-index"));return!t&&isNaN(e)&&(e=parseInt(this.$root.css("z-index"))),isNaN(e)?1:e},getTouchPoint:function(t){return t.touches&&t.touches[0]||t.changedTouches&&t.changedTouches[0]||t},getViewport:function(t){var e=t?"Height":"Width",i=document.documentElement["client"+e],s=window["inner"+e];return s&&(i=Math.min(i,s)),i},getViewportHeight:function(){return this.getViewport(!0)},getViewportWidth:function(){return this.getViewport()},getWidth:function(t){return this.getOffset(t)},handleEvents:function(){return!this.disabled&&this.isCSSOn()},handleItemEvents:function(t){return this.handleEvents()&&!this.isLinkInMegaMenu(t)},isCollapsible:function(){return"static"==this.$firstSub.css("position")},isCSSOn:function(){return"inline"!=this.$firstLink.css("display")},isFixed:function(){var t="fixed"==this.$root.css("position");return t||this.$root.parentsUntil("body").each(function(){return"fixed"==$(this).css("position")?(t=!0,!1):void 0}),t},isLinkInMegaMenu:function(t){return $(this.getClosestMenu(t[0])).hasClass("mega-menu")},isTouchMode:function(){return!mouse||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(t,e){var i=t.closest("ul"),s=i.dataSM("level");if(s>1&&(!this.activatedItems[s-2]||this.activatedItems[s-2][0]!=i.dataSM("parent-a")[0])){var o=this;$(i.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(i).each(function(){o.itemActivate($(this).dataSM("parent-a"))})}if((!this.isCollapsible()||e)&&this.menuHideSubMenus(this.activatedItems[s-1]&&this.activatedItems[s-1][0]==t[0]?s:s-1),this.activatedItems[s-1]=t,this.$root.triggerHandler("activate.smapi",t[0])!==!1){var a=t.dataSM("sub");a&&(this.isTouchMode()||!this.opts.showOnClick||this.clickActivated)&&this.menuShow(a)}},itemBlur:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&this.$root.triggerHandler("blur.smapi",e[0])},itemClick:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==e.closest("ul")[0])return this.$touchScrollingSub=null,t.stopPropagation(),!1;if(this.$root.triggerHandler("click.smapi",e[0])===!1)return!1;var i=$(t.target).is(".sub-arrow"),s=e.dataSM("sub"),o=s?2==s.dataSM("level"):!1,a=this.isCollapsible(),n=/toggle$/.test(this.opts.collapsibleBehavior),r=/link$/.test(this.opts.collapsibleBehavior),h=/^accordion/.test(this.opts.collapsibleBehavior);if(s&&!s.is(":visible")){if((!r||!a||i)&&(this.opts.showOnClick&&o&&(this.clickActivated=!0),this.itemActivate(e,h),s.is(":visible")))return this.focusActivated=!0,!1}else if(a&&(n||i))return this.itemActivate(e,h),this.menuHide(s),n&&(this.focusActivated=!1),!1;return this.opts.showOnClick&&o||e.hasClass("disabled")||this.$root.triggerHandler("select.smapi",e[0])===!1?!1:void 0}},itemDown:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&e.dataSM("mousedown",!0)},itemEnter:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(!this.isTouchMode()){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);var i=this;this.showTimeout=setTimeout(function(){i.itemActivate(e)},this.opts.showOnClick&&1==e.closest("ul").dataSM("level")?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",e[0])}},itemFocus:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(!this.focusActivated||this.isTouchMode()&&e.dataSM("mousedown")||this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0]==e[0]||this.itemActivate(e,!0),this.$root.triggerHandler("focus.smapi",e[0]))},itemLeave:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(this.isTouchMode()||(e[0].blur(),this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0)),e.removeDataSM("mousedown"),this.$root.triggerHandler("mouseleave.smapi",e[0]))},menuHide:function(t){if(this.$root.triggerHandler("beforehide.smapi",t[0])!==!1&&(canAnimate&&t.stop(!0,!0),"none"!=t.css("display"))){var e=function(){t.css("z-index","")};this.isCollapsible()?canAnimate&&this.opts.collapsibleHideFunction?this.opts.collapsibleHideFunction.call(this,t,e):t.hide(this.opts.collapsibleHideDuration,e):canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,t,e):t.hide(this.opts.hideDuration,e),t.dataSM("scroll")&&(this.menuScrollStop(t),t.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).off(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()),t.dataSM("parent-a").removeClass("highlighted").attr("aria-expanded","false"),t.attr({"aria-expanded":"false","aria-hidden":"true"});var i=t.dataSM("level");this.activatedItems.splice(i-1,1),this.visibleSubMenus.splice($.inArray(t,this.visibleSubMenus),1),this.$root.triggerHandler("hide.smapi",t[0])}},menuHideAll:function(){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);for(var t=this.opts.isPopup?1:0,e=this.visibleSubMenus.length-1;e>=t;e--)this.menuHide(this.visibleSubMenus[e]);this.opts.isPopup&&(canAnimate&&this.$root.stop(!0,!0),this.$root.is(":visible")&&(canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,this.$root):this.$root.hide(this.opts.hideDuration))),this.activatedItems=[],this.visibleSubMenus=[],this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(t){for(var e=this.activatedItems.length-1;e>=t;e--){var i=this.activatedItems[e].dataSM("sub");i&&this.menuHide(i)}},menuInit:function(t){if(!t.dataSM("in-mega")){t.hasClass("mega-menu")&&t.find("ul").dataSM("in-mega",!0);for(var e=2,i=t[0];(i=i.parentNode.parentNode)!=this.$root[0];)e++;var s=t.prevAll("a").eq(-1);s.length||(s=t.prevAll().find("a").eq(-1)),s.addClass("has-submenu").dataSM("sub",t),t.dataSM("parent-a",s).dataSM("level",e).parent().dataSM("sub",t);var o=s.attr("id")||this.accessIdPrefix+ ++this.idInc,a=t.attr("id")||this.accessIdPrefix+ ++this.idInc;s.attr({id:o,"aria-haspopup":"true","aria-controls":a,"aria-expanded":"false"}),t.attr({id:a,role:"group","aria-hidden":"true","aria-labelledby":o,"aria-expanded":"false"}),this.opts.subIndicators&&s[this.opts.subIndicatorsPos](this.$subArrow.clone())}},menuPosition:function(t){var e,i,s=t.dataSM("parent-a"),o=s.closest("li"),a=o.parent(),n=t.dataSM("level"),r=this.getWidth(t),h=this.getHeight(t),u=s.offset(),l=u.left,c=u.top,d=this.getWidth(s),m=this.getHeight(s),p=$(window),f=p.scrollLeft(),v=p.scrollTop(),b=this.getViewportWidth(),S=this.getViewportHeight(),g=a.parent().is("[data-sm-horizontal-sub]")||2==n&&!a.hasClass("sm-vertical"),M=this.opts.rightToLeftSubMenus&&!o.is("[data-sm-reverse]")||!this.opts.rightToLeftSubMenus&&o.is("[data-sm-reverse]"),w=2==n?this.opts.mainMenuSubOffsetX:this.opts.subMenusSubOffsetX,T=2==n?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY;if(g?(e=M?d-r-w:w,i=this.opts.bottomToTopSubMenus?-h-T:m+T):(e=M?w-r:d-w,i=this.opts.bottomToTopSubMenus?m-T-h:T),this.opts.keepInViewport){var y=l+e,I=c+i;if(M&&f>y?e=g?f-y+e:d-w:!M&&y+r>f+b&&(e=g?f+b-r-y+e:w-r),g||(S>h&&I+h>v+S?i+=v+S-h-I:(h>=S||v>I)&&(i+=v-I)),g&&(I+h>v+S+.49||v>I)||!g&&h>S+.49){var x=this;t.dataSM("scroll-arrows")||t.dataSM("scroll-arrows",$([$('')[0],$('')[0]]).on({mouseenter:function(){t.dataSM("scroll").up=$(this).hasClass("scroll-up"),x.menuScroll(t)},mouseleave:function(e){x.menuScrollStop(t),x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(t){t.preventDefault()}}).insertAfter(t));var A=".smartmenus_scroll";if(t.dataSM("scroll",{y:this.cssTransforms3d?0:i-m,step:1,itemH:m,subH:h,arrowDownH:this.getHeight(t.dataSM("scroll-arrows").eq(1))}).on(getEventsNS({mouseover:function(e){x.menuScrollOver(t,e)},mouseout:function(e){x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(e){x.menuScrollMousewheel(t,e)}},A)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:e+(parseInt(t.css("border-left-width"))||0),width:r-(parseInt(t.css("border-left-width"))||0)-(parseInt(t.css("border-right-width"))||0),zIndex:t.css("z-index")}).eq(g&&this.opts.bottomToTopSubMenus?0:1).show(),this.isFixed()){var C={};C[touchEvents?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp"]=function(e){x.menuScrollTouch(t,e)},t.css({"touch-action":"none","-ms-touch-action":"none"}).on(getEventsNS(C,A))}}}t.css({top:"auto",left:"0",marginLeft:e,marginTop:i-m})},menuScroll:function(t,e,i){var s,o=t.dataSM("scroll"),a=t.dataSM("scroll-arrows"),n=o.up?o.upEnd:o.downEnd;if(!e&&o.momentum){if(o.momentum*=.92,s=o.momentum,.5>s)return this.menuScrollStop(t),void 0}else s=i||(e||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(o.step));var r=t.dataSM("level");if(this.activatedItems[r-1]&&this.activatedItems[r-1].dataSM("sub")&&this.activatedItems[r-1].dataSM("sub").is(":visible")&&this.menuHideSubMenus(r-1),o.y=o.up&&o.y>=n||!o.up&&n>=o.y?o.y:Math.abs(n-o.y)>s?o.y+(o.up?s:-s):n,t.css(this.cssTransforms3d?{"-webkit-transform":"translate3d(0, "+o.y+"px, 0)",transform:"translate3d(0, "+o.y+"px, 0)"}:{marginTop:o.y}),mouse&&(o.up&&o.y>o.downEnd||!o.up&&o.y0;t.dataSM("scroll-arrows").eq(i?0:1).is(":visible")&&(t.dataSM("scroll").up=i,this.menuScroll(t,!0))}e.preventDefault()},menuScrollOut:function(t,e){mouse&&(/^scroll-(up|down)/.test((e.relatedTarget||"").className)||(t[0]==e.relatedTarget||$.contains(t[0],e.relatedTarget))&&this.getClosestMenu(e.relatedTarget)==t[0]||t.dataSM("scroll-arrows").css("visibility","hidden"))},menuScrollOver:function(t,e){if(mouse&&!/^scroll-(up|down)/.test(e.target.className)&&this.getClosestMenu(e.target)==t[0]){this.menuScrollRefreshData(t);var i=t.dataSM("scroll"),s=$(window).scrollTop()-t.dataSM("parent-a").offset().top-i.itemH;t.dataSM("scroll-arrows").eq(0).css("margin-top",s).end().eq(1).css("margin-top",s+this.getViewportHeight()-i.arrowDownH).end().css("visibility","visible")}},menuScrollRefreshData:function(t){var e=t.dataSM("scroll"),i=$(window).scrollTop()-t.dataSM("parent-a").offset().top-e.itemH;this.cssTransforms3d&&(i=-(parseFloat(t.css("margin-top"))-i)),$.extend(e,{upEnd:i,downEnd:i+this.getViewportHeight()-e.subH})},menuScrollStop:function(t){return this.scrollTimeout?(cancelAnimationFrame(this.scrollTimeout),this.scrollTimeout=0,t.dataSM("scroll").step=1,!0):void 0},menuScrollTouch:function(t,e){if(e=e.originalEvent,isTouchEvent(e)){var i=this.getTouchPoint(e);if(this.getClosestMenu(i.target)==t[0]){var s=t.dataSM("scroll");if(/(start|down)$/i.test(e.type))this.menuScrollStop(t)?(e.preventDefault(),this.$touchScrollingSub=t):this.$touchScrollingSub=null,this.menuScrollRefreshData(t),$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp});else if(/move$/i.test(e.type)){var o=void 0!==s.touchY?s.touchY:s.touchStartY;if(void 0!==o&&o!=i.pageY){this.$touchScrollingSub=t;var a=i.pageY>o;void 0!==s.up&&s.up!=a&&$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp}),$.extend(s,{up:a,touchY:i.pageY}),this.menuScroll(t,!0,Math.abs(i.pageY-o))}e.preventDefault()}else void 0!==s.touchY&&((s.momentum=15*Math.pow(Math.abs(i.pageY-s.touchStartY)/(e.timeStamp-s.touchStartTime),2))&&(this.menuScrollStop(t),this.menuScroll(t),e.preventDefault()),delete s.touchY)}}},menuShow:function(t){if((t.dataSM("beforefirstshowfired")||(t.dataSM("beforefirstshowfired",!0),this.$root.triggerHandler("beforefirstshow.smapi",t[0])!==!1))&&this.$root.triggerHandler("beforeshow.smapi",t[0])!==!1&&(t.dataSM("shown-before",!0),canAnimate&&t.stop(!0,!0),!t.is(":visible"))){var e=t.dataSM("parent-a"),i=this.isCollapsible();if((this.opts.keepHighlighted||i)&&e.addClass("highlighted"),i)t.removeClass("sm-nowrap").css({zIndex:"",width:"auto",minWidth:"",maxWidth:"",top:"",left:"",marginLeft:"",marginTop:""});else{if(t.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1),(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth)&&(t.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap"),this.opts.subMenusMinWidth&&t.css("min-width",this.opts.subMenusMinWidth),this.opts.subMenusMaxWidth)){var s=this.getWidth(t);t.css("max-width",this.opts.subMenusMaxWidth),s>this.getWidth(t)&&t.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}this.menuPosition(t)}var o=function(){t.css("overflow","")};i?canAnimate&&this.opts.collapsibleShowFunction?this.opts.collapsibleShowFunction.call(this,t,o):t.show(this.opts.collapsibleShowDuration,o):canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,t,o):t.show(this.opts.showDuration,o),e.attr("aria-expanded","true"),t.attr({"aria-expanded":"true","aria-hidden":"false"}),this.visibleSubMenus.push(t),this.$root.triggerHandler("show.smapi",t[0])}},popupHide:function(t){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},t?1:this.opts.hideTimeout)},popupShow:function(t,e){if(!this.opts.isPopup)return alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'),void 0;if(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),this.$root.dataSM("shown-before",!0),canAnimate&&this.$root.stop(!0,!0),!this.$root.is(":visible")){this.$root.css({left:t,top:e});var i=this,s=function(){i.$root.css("overflow","")};canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,this.$root,s):this.$root.show(this.opts.showDuration,s),this.visibleSubMenus[0]=this.$root}},refresh:function(){this.destroy(!0),this.init(!0)},rootKeyDown:function(t){if(this.handleEvents())switch(t.keyCode){case 27:var e=this.activatedItems[0];if(e){this.menuHideAll(),e[0].focus();var i=e.dataSM("sub");i&&this.menuHide(i)}break;case 32:var s=$(t.target);if(s.is("a")&&this.handleItemEvents(s)){var i=s.dataSM("sub");i&&!i.is(":visible")&&(this.itemClick({currentTarget:t.target}),t.preventDefault())}}},rootOut:function(t){if(this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),!this.opts.showOnClick||!this.opts.hideOnClick)){var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},this.opts.hideTimeout)}},rootOver:function(t){this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0)},winResize:function(t){if(this.handleEvents()){if(!("onorientationchange"in window)||"orientationchange"==t.type){var e=this.isCollapsible();this.wasCollapsible&&e||(this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0].blur(),this.menuHideAll()),this.wasCollapsible=e}}else if(this.$disableOverlay){var i=this.$root.offset();this.$disableOverlay.css({top:i.top,left:i.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}}}}),$.fn.dataSM=function(t,e){return e?this.data(t+"_smartmenus",e):this.data(t+"_smartmenus")},$.fn.removeDataSM=function(t){return this.removeData(t+"_smartmenus")},$.fn.smartmenus=function(options){if("string"==typeof options){var args=arguments,method=options;return Array.prototype.shift.call(args),this.each(function(){var t=$(this).data("smartmenus");t&&t[method]&&t[method].apply(t,args)})}return this.each(function(){var dataOpts=$(this).data("sm-options")||null;if(dataOpts)try{dataOpts=eval("("+dataOpts+")")}catch(e){dataOpts=null,alert('ERROR\n\nSmartMenus jQuery init:\nInvalid "data-sm-options" attribute value syntax.')}new $.SmartMenus(this,$.extend({},$.fn.smartmenus.defaults,options,dataOpts))})},$.fn.smartmenus.defaults={isPopup:!1,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:!0,subIndicatorsPos:"append",subIndicatorsText:"",scrollStep:30,scrollAccelerate:!0,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(t,e){t.fadeOut(200,e)},collapsibleShowDuration:0,collapsibleShowFunction:function(t,e){t.slideDown(200,e)},collapsibleHideDuration:0,collapsibleHideFunction:function(t,e){t.slideUp(200,e)},showOnClick:!1,hideOnClick:!0,noMouseOver:!1,keepInViewport:!0,keepHighlighted:!0,markCurrentItem:!1,markCurrentTree:!0,rightToLeftSubMenus:!1,bottomToTopSubMenus:!1,collapsibleBehavior:"default"},$}); \ No newline at end of file diff --git a/1.2/reference/json_8h_source.html b/1.2/reference/json_8h_source.html new file mode 100644 index 000000000..17be4a80c --- /dev/null +++ b/1.2/reference/json_8h_source.html @@ -0,0 +1,2224 @@ + + + + + + + + Crow: include/crow/json.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
json.h
+
+
+
1 #pragma once
+
2 
+
3 //#define CROW_JSON_NO_ERROR_CHECK
+
4 //#define CROW_JSON_USE_MAP
+
5 
+
6 #include <string>
+
7 #ifdef CROW_JSON_USE_MAP
+
8 #include <map>
+
9 #else
+
10 #include <unordered_map>
+
11 #endif
+
12 #include <iostream>
+
13 #include <algorithm>
+
14 #include <memory>
+
15 #include <vector>
+
16 #include <cmath>
+
17 #include <cfloat>
+
18 
+
19 #include "crow/utility.h"
+
20 #include "crow/settings.h"
+
21 #include "crow/returnable.h"
+
22 #include "crow/logging.h"
+
23 
+
24 using std::isinf;
+
25 using std::isnan;
+
26 
+
27 
+
28 namespace crow // NOTE: Already documented in "crow/app.h"
+
29 {
+
30  namespace mustache
+
31  {
+
32  class template_t;
+
33  }
+
34 
+
35  namespace json
+
36  {
+
37  inline void escape(const std::string& str, std::string& ret)
+
38  {
+
39  ret.reserve(ret.size() + str.size() + str.size() / 4);
+
40  for (auto c : str)
+
41  {
+
42  switch (c)
+
43  {
+
44  case '"': ret += "\\\""; break;
+
45  case '\\': ret += "\\\\"; break;
+
46  case '\n': ret += "\\n"; break;
+
47  case '\b': ret += "\\b"; break;
+
48  case '\f': ret += "\\f"; break;
+
49  case '\r': ret += "\\r"; break;
+
50  case '\t': ret += "\\t"; break;
+
51  default:
+
52  if (c >= 0 && c < 0x20)
+
53  {
+
54  ret += "\\u00";
+
55  auto to_hex = [](char c) {
+
56  c = c & 0xf;
+
57  if (c < 10)
+
58  return '0' + c;
+
59  return 'a' + c - 10;
+
60  };
+
61  ret += to_hex(c / 16);
+
62  ret += to_hex(c % 16);
+
63  }
+
64  else
+
65  ret += c;
+
66  break;
+
67  }
+
68  }
+
69  }
+
70  inline std::string escape(const std::string& str)
+
71  {
+
72  std::string ret;
+
73  escape(str, ret);
+
74  return ret;
+
75  }
+
76 
+
77  enum class type : char
+
78  {
+
79  Null,
+
80  False,
+
81  True,
+
82  Number,
+
83  String,
+
84  List,
+
85  Object,
+
86  Function
+
87  };
+
88 
+
89  inline const char* get_type_str(type t)
+
90  {
+
91  switch (t)
+
92  {
+
93  case type::Number: return "Number";
+
94  case type::False: return "False";
+
95  case type::True: return "True";
+
96  case type::List: return "List";
+
97  case type::String: return "String";
+
98  case type::Object: return "Object";
+
99  case type::Function: return "Function";
+
100  default: return "Unknown";
+
101  }
+
102  }
+
103 
+
104  enum class num_type : char
+
105  {
+
106  Signed_integer,
+
107  Unsigned_integer,
+
108  Floating_point,
+
109  Null,
+
110  Double_precision_floating_point
+
111  };
+
112 
+
113  class rvalue;
+
114  rvalue load(const char* data, size_t size);
+
115 
+
116  namespace detail
+
117  {
+
118  /// A read string implementation with comparison functionality.
+
119  struct r_string
+
120  {
+
121  r_string(){};
+
122  r_string(char* s, char* e):
+
123  s_(s), e_(e){};
+
124  ~r_string()
+
125  {
+
126  if (owned_)
+
127  delete[] s_;
+
128  }
+
129 
+
130  r_string(const r_string& r)
+
131  {
+
132  *this = r;
+
133  }
+
134 
+
135  r_string(r_string&& r)
+
136  {
+
137  *this = r;
+
138  }
+
139 
+
140  r_string& operator=(r_string&& r)
+
141  {
+
142  s_ = r.s_;
+
143  e_ = r.e_;
+
144  owned_ = r.owned_;
+
145  if (r.owned_)
+
146  r.owned_ = 0;
+
147  return *this;
+
148  }
+
149 
+
150  r_string& operator=(const r_string& r)
+
151  {
+
152  s_ = r.s_;
+
153  e_ = r.e_;
+
154  owned_ = 0;
+
155  return *this;
+
156  }
+
157 
+
158  operator std::string() const
+
159  {
+
160  return std::string(s_, e_);
+
161  }
+
162 
+
163 
+
164  const char* begin() const { return s_; }
+
165  const char* end() const { return e_; }
+
166  size_t size() const { return end() - begin(); }
+
167 
+
168  using iterator = const char*;
+
169  using const_iterator = const char*;
+
170 
+
171  char* s_; ///< Start.
+
172  mutable char* e_; ///< End.
+
173  uint8_t owned_{0};
+
174  friend std::ostream& operator<<(std::ostream& os, const r_string& s)
+
175  {
+
176  os << static_cast<std::string>(s);
+
177  return os;
+
178  }
+
179 
+
180  private:
+
181  void force(char* s, uint32_t length)
+
182  {
+
183  s_ = s;
+
184  e_ = s_ + length;
+
185  owned_ = 1;
+
186  }
+
187  friend rvalue crow::json::load(const char* data, size_t size);
+
188 
+
189  friend bool operator==(const r_string& l, const r_string& r);
+
190  friend bool operator==(const std::string& l, const r_string& r);
+
191  friend bool operator==(const r_string& l, const std::string& r);
+
192 
+
193  template<typename T, typename U>
+
194  inline static bool equals(const T& l, const U& r)
+
195  {
+
196  if (l.size() != r.size())
+
197  return false;
+
198 
+
199  for (size_t i = 0; i < l.size(); i++)
+
200  {
+
201  if (*(l.begin() + i) != *(r.begin() + i))
+
202  return false;
+
203  }
+
204 
+
205  return true;
+
206  }
+
207  };
+
208 
+
209  inline bool operator<(const r_string& l, const r_string& r)
+
210  {
+
211  return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
+
212  }
+
213 
+
214  inline bool operator<(const r_string& l, const std::string& r)
+
215  {
+
216  return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
+
217  }
+
218 
+
219  inline bool operator<(const std::string& l, const r_string& r)
+
220  {
+
221  return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
+
222  }
+
223 
+
224  inline bool operator>(const r_string& l, const r_string& r)
+
225  {
+
226  return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
+
227  }
+
228 
+
229  inline bool operator>(const r_string& l, const std::string& r)
+
230  {
+
231  return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
+
232  }
+
233 
+
234  inline bool operator>(const std::string& l, const r_string& r)
+
235  {
+
236  return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
+
237  }
+
238 
+
239  inline bool operator==(const r_string& l, const r_string& r)
+
240  {
+
241  return r_string::equals(l, r);
+
242  }
+
243 
+
244  inline bool operator==(const r_string& l, const std::string& r)
+
245  {
+
246  return r_string::equals(l, r);
+
247  }
+
248 
+
249  inline bool operator==(const std::string& l, const r_string& r)
+
250  {
+
251  return r_string::equals(l, r);
+
252  }
+
253 
+
254  inline bool operator!=(const r_string& l, const r_string& r)
+
255  {
+
256  return !(l == r);
+
257  }
+
258 
+
259  inline bool operator!=(const r_string& l, const std::string& r)
+
260  {
+
261  return !(l == r);
+
262  }
+
263 
+
264  inline bool operator!=(const std::string& l, const r_string& r)
+
265  {
+
266  return !(l == r);
+
267  }
+
268  } // namespace detail
+
269 
+
270  /// JSON read value.
+
271 
+
272  ///
+
273  /// Value can mean any json value, including a JSON object.
+
274  /// Read means this class is used to primarily read strings into a JSON value.
+
275  class rvalue
+
276  {
+
277  static const int cached_bit = 2;
+
278  static const int error_bit = 4;
+
279 
+
280  public:
+
281  rvalue() noexcept:
+
282  option_{error_bit}
+
283  {
+
284  }
+
285  rvalue(type t) noexcept:
+
286  lsize_{}, lremain_{}, t_{t}
+
287  {
+
288  }
+
289  rvalue(type t, char* s, char* e) noexcept:
+
290  start_{s}, end_{e}, t_{t}
+
291  {
+
292  determine_num_type();
+
293  }
+
294 
+
295  rvalue(const rvalue& r):
+
296  start_(r.start_), end_(r.end_), key_(r.key_), t_(r.t_), nt_(r.nt_), option_(r.option_)
+
297  {
+
298  copy_l(r);
+
299  }
+
300 
+
301  rvalue(rvalue&& r) noexcept
+
302  {
+
303  *this = std::move(r);
+
304  }
+
305 
+
306  rvalue& operator=(const rvalue& r)
+
307  {
+
308  start_ = r.start_;
+
309  end_ = r.end_;
+
310  key_ = r.key_;
+
311  t_ = r.t_;
+
312  nt_ = r.nt_;
+
313  option_ = r.option_;
+
314  copy_l(r);
+
315  return *this;
+
316  }
+
317  rvalue& operator=(rvalue&& r) noexcept
+
318  {
+
319  start_ = r.start_;
+
320  end_ = r.end_;
+
321  key_ = std::move(r.key_);
+
322  l_ = std::move(r.l_);
+
323  lsize_ = r.lsize_;
+
324  lremain_ = r.lremain_;
+
325  t_ = r.t_;
+
326  nt_ = r.nt_;
+
327  option_ = r.option_;
+
328  return *this;
+
329  }
+
330 
+
331  explicit operator bool() const noexcept
+
332  {
+
333  return (option_ & error_bit) == 0;
+
334  }
+
335 
+
336  explicit operator int64_t() const
+
337  {
+
338  return i();
+
339  }
+
340 
+
341  explicit operator uint64_t() const
+
342  {
+
343  return u();
+
344  }
+
345 
+
346  explicit operator int() const
+
347  {
+
348  return static_cast<int>(i());
+
349  }
+
350 
+
351  /// Return any json value (not object or list) as a string.
+
352  explicit operator std::string() const
+
353  {
+
354 #ifndef CROW_JSON_NO_ERROR_CHECK
+
355  if (t() == type::Object || t() == type::List)
+
356  throw std::runtime_error("json type container");
+
357 #endif
+
358  switch (t())
+
359  {
+
360  case type::String:
+
361  return std::string(s());
+
362  case type::Null:
+
363  return std::string("null");
+
364  case type::True:
+
365  return std::string("true");
+
366  case type::False:
+
367  return std::string("false");
+
368  default:
+
369  return std::string(start_, end_ - start_);
+
370  }
+
371  }
+
372 
+
373  /// The type of the JSON value.
+
374  type t() const
+
375  {
+
376 #ifndef CROW_JSON_NO_ERROR_CHECK
+
377  if (option_ & error_bit)
+
378  {
+
379  throw std::runtime_error("invalid json object");
+
380  }
+
381 #endif
+
382  return t_;
+
383  }
+
384 
+
385  /// The number type of the JSON value.
+
386  num_type nt() const
+
387  {
+
388 #ifndef CROW_JSON_NO_ERROR_CHECK
+
389  if (option_ & error_bit)
+
390  {
+
391  throw std::runtime_error("invalid json object");
+
392  }
+
393 #endif
+
394  return nt_;
+
395  }
+
396 
+
397  /// The integer value.
+
398  int64_t i() const
+
399  {
+
400 #ifndef CROW_JSON_NO_ERROR_CHECK
+
401  switch (t())
+
402  {
+
403  case type::Number:
+
404  case type::String:
+
405  return utility::lexical_cast<int64_t>(start_, end_ - start_);
+
406  default:
+
407  const std::string msg = "expected number, got: " + std::string(get_type_str(t()));
+
408  throw std::runtime_error(msg);
+
409  }
+
410 #endif
+
411  return utility::lexical_cast<int64_t>(start_, end_ - start_);
+
412  }
+
413 
+
414  /// The unsigned integer value.
+
415  uint64_t u() const
+
416  {
+
417 #ifndef CROW_JSON_NO_ERROR_CHECK
+
418  switch (t())
+
419  {
+
420  case type::Number:
+
421  case type::String:
+
422  return utility::lexical_cast<uint64_t>(start_, end_ - start_);
+
423  default:
+
424  throw std::runtime_error(std::string("expected number, got: ") + get_type_str(t()));
+
425  }
+
426 #endif
+
427  return utility::lexical_cast<uint64_t>(start_, end_ - start_);
+
428  }
+
429 
+
430  /// The double precision floating-point number value.
+
431  double d() const
+
432  {
+
433 #ifndef CROW_JSON_NO_ERROR_CHECK
+
434  if (t() != type::Number)
+
435  throw std::runtime_error("value is not number");
+
436 #endif
+
437  return utility::lexical_cast<double>(start_, end_ - start_);
+
438  }
+
439 
+
440  /// The boolean value.
+
441  bool b() const
+
442  {
+
443 #ifndef CROW_JSON_NO_ERROR_CHECK
+
444  if (t() != type::True && t() != type::False)
+
445  throw std::runtime_error("value is not boolean");
+
446 #endif
+
447  return t() == type::True;
+
448  }
+
449 
+
450  /// The string value.
+ +
452  {
+
453 #ifndef CROW_JSON_NO_ERROR_CHECK
+
454  if (t() != type::String)
+
455  throw std::runtime_error("value is not string");
+
456 #endif
+
457  unescape();
+
458  return detail::r_string{start_, end_};
+
459  }
+
460 
+
461  /// The list or object value
+
462  std::vector<rvalue> lo()
+
463  {
+
464 #ifndef CROW_JSON_NO_ERROR_CHECK
+
465  if (t() != type::Object && t() != type::List)
+
466  throw std::runtime_error("value is not a container");
+
467 #endif
+
468  std::vector<rvalue> ret;
+
469  ret.reserve(lsize_);
+
470  for (uint32_t i = 0; i < lsize_; i++)
+
471  {
+
472  ret.emplace_back(l_[i]);
+
473  }
+
474  return ret;
+
475  }
+
476 
+
477  /// Convert escaped string character to their original form ("\\n" -> '\n').
+
478  void unescape() const
+
479  {
+
480  if (*(start_ - 1))
+
481  {
+
482  char* head = start_;
+
483  char* tail = start_;
+
484  while (head != end_)
+
485  {
+
486  if (*head == '\\')
+
487  {
+
488  switch (*++head)
+
489  {
+
490  case '"': *tail++ = '"'; break;
+
491  case '\\': *tail++ = '\\'; break;
+
492  case '/': *tail++ = '/'; break;
+
493  case 'b': *tail++ = '\b'; break;
+
494  case 'f': *tail++ = '\f'; break;
+
495  case 'n': *tail++ = '\n'; break;
+
496  case 'r': *tail++ = '\r'; break;
+
497  case 't': *tail++ = '\t'; break;
+
498  case 'u':
+
499  {
+
500  auto from_hex = [](char c) {
+
501  if (c >= 'a')
+
502  return c - 'a' + 10;
+
503  if (c >= 'A')
+
504  return c - 'A' + 10;
+
505  return c - '0';
+
506  };
+
507  unsigned int code =
+
508  (from_hex(head[1]) << 12) +
+
509  (from_hex(head[2]) << 8) +
+
510  (from_hex(head[3]) << 4) +
+
511  from_hex(head[4]);
+
512  if (code >= 0x800)
+
513  {
+
514  *tail++ = 0xE0 | (code >> 12);
+
515  *tail++ = 0x80 | ((code >> 6) & 0x3F);
+
516  *tail++ = 0x80 | (code & 0x3F);
+
517  }
+
518  else if (code >= 0x80)
+
519  {
+
520  *tail++ = 0xC0 | (code >> 6);
+
521  *tail++ = 0x80 | (code & 0x3F);
+
522  }
+
523  else
+
524  {
+
525  *tail++ = code;
+
526  }
+
527  head += 4;
+
528  }
+
529  break;
+
530  }
+
531  }
+
532  else
+
533  *tail++ = *head;
+
534  head++;
+
535  }
+
536  end_ = tail;
+
537  *end_ = 0;
+
538  *(start_ - 1) = 0;
+
539  }
+
540  }
+
541 
+
542  /// Check if the json object has the passed string as a key.
+
543  bool has(const char* str) const
+
544  {
+
545  return has(std::string(str));
+
546  }
+
547 
+
548  bool has(const std::string& str) const
+
549  {
+
550  struct Pred
+
551  {
+
552  bool operator()(const rvalue& l, const rvalue& r) const
+
553  {
+
554  return l.key_ < r.key_;
+
555  };
+
556  bool operator()(const rvalue& l, const std::string& r) const
+
557  {
+
558  return l.key_ < r;
+
559  };
+
560  bool operator()(const std::string& l, const rvalue& r) const
+
561  {
+
562  return l < r.key_;
+
563  };
+
564  };
+
565  if (!is_cached())
+
566  {
+
567  std::sort(begin(), end(), Pred());
+
568  set_cached();
+
569  }
+
570  auto it = lower_bound(begin(), end(), str, Pred());
+
571  return it != end() && it->key_ == str;
+
572  }
+
573 
+
574  int count(const std::string& str)
+
575  {
+
576  return has(str) ? 1 : 0;
+
577  }
+
578 
+
579  rvalue* begin() const
+
580  {
+
581 #ifndef CROW_JSON_NO_ERROR_CHECK
+
582  if (t() != type::Object && t() != type::List)
+
583  throw std::runtime_error("value is not a container");
+
584 #endif
+
585  return l_.get();
+
586  }
+
587  rvalue* end() const
+
588  {
+
589 #ifndef CROW_JSON_NO_ERROR_CHECK
+
590  if (t() != type::Object && t() != type::List)
+
591  throw std::runtime_error("value is not a container");
+
592 #endif
+
593  return l_.get() + lsize_;
+
594  }
+
595 
+
596  const detail::r_string& key() const
+
597  {
+
598  return key_;
+
599  }
+
600 
+
601  size_t size() const
+
602  {
+
603  if (t() == type::String)
+
604  return s().size();
+
605 #ifndef CROW_JSON_NO_ERROR_CHECK
+
606  if (t() != type::Object && t() != type::List)
+
607  throw std::runtime_error("value is not a container");
+
608 #endif
+
609  return lsize_;
+
610  }
+
611 
+
612  const rvalue& operator[](int index) const
+
613  {
+
614 #ifndef CROW_JSON_NO_ERROR_CHECK
+
615  if (t() != type::List)
+
616  throw std::runtime_error("value is not a list");
+
617  if (index >= static_cast<int>(lsize_) || index < 0)
+
618  throw std::runtime_error("list out of bound");
+
619 #endif
+
620  return l_[index];
+
621  }
+
622 
+
623  const rvalue& operator[](size_t index) const
+
624  {
+
625 #ifndef CROW_JSON_NO_ERROR_CHECK
+
626  if (t() != type::List)
+
627  throw std::runtime_error("value is not a list");
+
628  if (index >= lsize_)
+
629  throw std::runtime_error("list out of bound");
+
630 #endif
+
631  return l_[index];
+
632  }
+
633 
+
634  const rvalue& operator[](const char* str) const
+
635  {
+
636  return this->operator[](std::string(str));
+
637  }
+
638 
+
639  const rvalue& operator[](const std::string& str) const
+
640  {
+
641 #ifndef CROW_JSON_NO_ERROR_CHECK
+
642  if (t() != type::Object)
+
643  throw std::runtime_error("value is not an object");
+
644 #endif
+
645  struct Pred
+
646  {
+
647  bool operator()(const rvalue& l, const rvalue& r) const
+
648  {
+
649  return l.key_ < r.key_;
+
650  };
+
651  bool operator()(const rvalue& l, const std::string& r) const
+
652  {
+
653  return l.key_ < r;
+
654  };
+
655  bool operator()(const std::string& l, const rvalue& r) const
+
656  {
+
657  return l < r.key_;
+
658  };
+
659  };
+
660  if (!is_cached())
+
661  {
+
662  std::sort(begin(), end(), Pred());
+
663  set_cached();
+
664  }
+
665  auto it = lower_bound(begin(), end(), str, Pred());
+
666  if (it != end() && it->key_ == str)
+
667  return *it;
+
668 #ifndef CROW_JSON_NO_ERROR_CHECK
+
669  throw std::runtime_error("cannot find key");
+
670 #else
+
671  static rvalue nullValue;
+
672  return nullValue;
+
673 #endif
+
674  }
+
675 
+
676  void set_error()
+
677  {
+
678  option_ |= error_bit;
+
679  }
+
680 
+
681  bool error() const
+
682  {
+
683  return (option_ & error_bit) != 0;
+
684  }
+
685 
+
686  std::vector<std::string> keys() const
+
687  {
+
688 #ifndef CROW_JSON_NO_ERROR_CHECK
+
689  if (t() != type::Object)
+
690  throw std::runtime_error("value is not an object");
+
691 #endif
+
692  std::vector<std::string> ret;
+
693  ret.reserve(lsize_);
+
694  for (uint32_t i = 0; i < lsize_; i++)
+
695  {
+
696  ret.emplace_back(std::string(l_[i].key()));
+
697  }
+
698  return ret;
+
699  }
+
700 
+
701  private:
+
702  bool is_cached() const
+
703  {
+
704  return (option_ & cached_bit) != 0;
+
705  }
+
706  void set_cached() const
+
707  {
+
708  option_ |= cached_bit;
+
709  }
+
710  void copy_l(const rvalue& r)
+
711  {
+
712  if (r.t() != type::Object && r.t() != type::List)
+
713  return;
+
714  lsize_ = r.lsize_;
+
715  lremain_ = 0;
+
716  l_.reset(new rvalue[lsize_]);
+
717  std::copy(r.begin(), r.end(), begin());
+
718  }
+
719 
+
720  void emplace_back(rvalue&& v)
+
721  {
+
722  if (!lremain_)
+
723  {
+
724  int new_size = lsize_ + lsize_;
+
725  if (new_size - lsize_ > 60000)
+
726  new_size = lsize_ + 60000;
+
727  if (new_size < 4)
+
728  new_size = 4;
+
729  rvalue* p = new rvalue[new_size];
+
730  rvalue* p2 = p;
+
731  for (auto& x : *this)
+
732  *p2++ = std::move(x);
+
733  l_.reset(p);
+
734  lremain_ = new_size - lsize_;
+
735  }
+
736  l_[lsize_++] = std::move(v);
+
737  lremain_--;
+
738  }
+
739 
+
740  /// Determines num_type from the string.
+
741  void determine_num_type()
+
742  {
+
743  if (t_ != type::Number)
+
744  {
+
745  nt_ = num_type::Null;
+
746  return;
+
747  }
+
748 
+
749  const std::size_t len = end_ - start_;
+
750  const bool has_minus = std::memchr(start_, '-', len) != nullptr;
+
751  const bool has_e = std::memchr(start_, 'e', len) != nullptr || std::memchr(start_, 'E', len) != nullptr;
+
752  const bool has_dec_sep = std::memchr(start_, '.', len) != nullptr;
+
753  if (has_dec_sep || has_e)
+
754  nt_ = num_type::Floating_point;
+
755  else if (has_minus)
+
756  nt_ = num_type::Signed_integer;
+
757  else
+
758  nt_ = num_type::Unsigned_integer;
+
759  }
+
760 
+
761  mutable char* start_;
+
762  mutable char* end_;
+
763  detail::r_string key_;
+
764  std::unique_ptr<rvalue[]> l_;
+
765  uint32_t lsize_;
+
766  uint16_t lremain_;
+
767  type t_;
+
768  num_type nt_{num_type::Null};
+
769  mutable uint8_t option_{0};
+
770 
+
771  friend rvalue load_nocopy_internal(char* data, size_t size);
+
772  friend rvalue load(const char* data, size_t size);
+
773  friend std::ostream& operator<<(std::ostream& os, const rvalue& r)
+
774  {
+
775  switch (r.t_)
+
776  {
+
777 
+
778  case type::Null: os << "null"; break;
+
779  case type::False: os << "false"; break;
+
780  case type::True: os << "true"; break;
+
781  case type::Number:
+
782  {
+
783  switch (r.nt())
+
784  {
+
785  case num_type::Floating_point: os << r.d(); break;
+
786  case num_type::Double_precision_floating_point: os << r.d(); break;
+
787  case num_type::Signed_integer: os << r.i(); break;
+
788  case num_type::Unsigned_integer: os << r.u(); break;
+
789  case num_type::Null: throw std::runtime_error("Number with num_type Null");
+
790  }
+
791  }
+
792  break;
+
793  case type::String: os << '"' << r.s() << '"'; break;
+
794  case type::List:
+
795  {
+
796  os << '[';
+
797  bool first = true;
+
798  for (auto& x : r)
+
799  {
+
800  if (!first)
+
801  os << ',';
+
802  first = false;
+
803  os << x;
+
804  }
+
805  os << ']';
+
806  }
+
807  break;
+
808  case type::Object:
+
809  {
+
810  os << '{';
+
811  bool first = true;
+
812  for (auto& x : r)
+
813  {
+
814  if (!first)
+
815  os << ',';
+
816  os << '"' << escape(x.key_) << "\":";
+
817  first = false;
+
818  os << x;
+
819  }
+
820  os << '}';
+
821  }
+
822  break;
+
823  case type::Function: os << "custom function"; break;
+
824  }
+
825  return os;
+
826  }
+
827  };
+
828  namespace detail
+
829  {
+
830  }
+
831 
+
832  inline bool operator==(const rvalue& l, const std::string& r)
+
833  {
+
834  return l.s() == r;
+
835  }
+
836 
+
837  inline bool operator==(const std::string& l, const rvalue& r)
+
838  {
+
839  return l == r.s();
+
840  }
+
841 
+
842  inline bool operator!=(const rvalue& l, const std::string& r)
+
843  {
+
844  return l.s() != r;
+
845  }
+
846 
+
847  inline bool operator!=(const std::string& l, const rvalue& r)
+
848  {
+
849  return l != r.s();
+
850  }
+
851 
+
852  inline bool operator==(const rvalue& l, double r)
+
853  {
+
854  return l.d() == r;
+
855  }
+
856 
+
857  inline bool operator==(double l, const rvalue& r)
+
858  {
+
859  return l == r.d();
+
860  }
+
861 
+
862  inline bool operator!=(const rvalue& l, double r)
+
863  {
+
864  return l.d() != r;
+
865  }
+
866 
+
867  inline bool operator!=(double l, const rvalue& r)
+
868  {
+
869  return l != r.d();
+
870  }
+
871 
+
872 
+
873  inline rvalue load_nocopy_internal(char* data, size_t size)
+
874  {
+
875  // Defend against excessive recursion
+
876  static constexpr unsigned max_depth = 10000;
+
877 
+
878  //static const char* escaped = "\"\\/\b\f\n\r\t";
+
879  struct Parser
+
880  {
+
881  Parser(char* data, size_t /*size*/):
+
882  data(data)
+
883  {
+
884  }
+
885 
+
886  bool consume(char c)
+
887  {
+
888  if (CROW_UNLIKELY(*data != c))
+
889  return false;
+
890  data++;
+
891  return true;
+
892  }
+
893 
+
894  void ws_skip()
+
895  {
+
896  while (*data == ' ' || *data == '\t' || *data == '\r' || *data == '\n')
+
897  ++data;
+
898  };
+
899 
+
900  rvalue decode_string()
+
901  {
+
902  if (CROW_UNLIKELY(!consume('"')))
+
903  return {};
+
904  char* start = data;
+
905  uint8_t has_escaping = 0;
+
906  while (1)
+
907  {
+
908  if (CROW_LIKELY(*data != '"' && *data != '\\' && *data != '\0'))
+
909  {
+
910  data++;
+
911  }
+
912  else if (*data == '"')
+
913  {
+
914  *data = 0;
+
915  *(start - 1) = has_escaping;
+
916  data++;
+
917  return {type::String, start, data - 1};
+
918  }
+
919  else if (*data == '\\')
+
920  {
+
921  has_escaping = 1;
+
922  data++;
+
923  switch (*data)
+
924  {
+
925  case 'u':
+
926  {
+
927  auto check = [](char c) {
+
928  return ('0' <= c && c <= '9') ||
+
929  ('a' <= c && c <= 'f') ||
+
930  ('A' <= c && c <= 'F');
+
931  };
+
932  if (!(check(*(data + 1)) &&
+
933  check(*(data + 2)) &&
+
934  check(*(data + 3)) &&
+
935  check(*(data + 4))))
+
936  return {};
+
937  }
+
938  data += 5;
+
939  break;
+
940  case '"':
+
941  case '\\':
+
942  case '/':
+
943  case 'b':
+
944  case 'f':
+
945  case 'n':
+
946  case 'r':
+
947  case 't':
+
948  data++;
+
949  break;
+
950  default:
+
951  return {};
+
952  }
+
953  }
+
954  else
+
955  return {};
+
956  }
+
957  return {};
+
958  }
+
959 
+
960  rvalue decode_list(unsigned depth)
+
961  {
+
962  rvalue ret(type::List);
+
963  if (CROW_UNLIKELY(!consume('[')) || CROW_UNLIKELY(depth > max_depth))
+
964  {
+
965  ret.set_error();
+
966  return ret;
+
967  }
+
968  ws_skip();
+
969  if (CROW_UNLIKELY(*data == ']'))
+
970  {
+
971  data++;
+
972  return ret;
+
973  }
+
974 
+
975  while (1)
+
976  {
+
977  auto v = decode_value(depth + 1);
+
978  if (CROW_UNLIKELY(!v))
+
979  {
+
980  ret.set_error();
+
981  break;
+
982  }
+
983  ws_skip();
+
984  ret.emplace_back(std::move(v));
+
985  if (*data == ']')
+
986  {
+
987  data++;
+
988  break;
+
989  }
+
990  if (CROW_UNLIKELY(!consume(',')))
+
991  {
+
992  ret.set_error();
+
993  break;
+
994  }
+
995  ws_skip();
+
996  }
+
997  return ret;
+
998  }
+
999 
+
1000  rvalue decode_number()
+
1001  {
+
1002  char* start = data;
+
1003 
+
1004  enum NumberParsingState
+
1005  {
+
1006  Minus,
+
1007  AfterMinus,
+
1008  ZeroFirst,
+
1009  Digits,
+
1010  DigitsAfterPoints,
+
1011  E,
+
1012  DigitsAfterE,
+
1013  Invalid,
+
1014  } state{Minus};
+
1015  while (CROW_LIKELY(state != Invalid))
+
1016  {
+
1017  switch (*data)
+
1018  {
+
1019  case '0':
+
1020  state = static_cast<NumberParsingState>("\2\2\7\3\4\6\6"[state]);
+
1021  /*if (state == NumberParsingState::Minus || state == NumberParsingState::AfterMinus)
+
1022  {
+
1023  state = NumberParsingState::ZeroFirst;
+
1024  }
+
1025  else if (state == NumberParsingState::Digits ||
+
1026  state == NumberParsingState::DigitsAfterE ||
+
1027  state == NumberParsingState::DigitsAfterPoints)
+
1028  {
+
1029  // ok; pass
+
1030  }
+
1031  else if (state == NumberParsingState::E)
+
1032  {
+
1033  state = NumberParsingState::DigitsAfterE;
+
1034  }
+
1035  else
+
1036  return {};*/
+
1037  break;
+
1038  case '1':
+
1039  case '2':
+
1040  case '3':
+
1041  case '4':
+
1042  case '5':
+
1043  case '6':
+
1044  case '7':
+
1045  case '8':
+
1046  case '9':
+
1047  state = static_cast<NumberParsingState>("\3\3\7\3\4\6\6"[state]);
+
1048  while (*(data + 1) >= '0' && *(data + 1) <= '9')
+
1049  data++;
+
1050  /*if (state == NumberParsingState::Minus || state == NumberParsingState::AfterMinus)
+
1051  {
+
1052  state = NumberParsingState::Digits;
+
1053  }
+
1054  else if (state == NumberParsingState::Digits ||
+
1055  state == NumberParsingState::DigitsAfterE ||
+
1056  state == NumberParsingState::DigitsAfterPoints)
+
1057  {
+
1058  // ok; pass
+
1059  }
+
1060  else if (state == NumberParsingState::E)
+
1061  {
+
1062  state = NumberParsingState::DigitsAfterE;
+
1063  }
+
1064  else
+
1065  return {};*/
+
1066  break;
+
1067  case '.':
+
1068  state = static_cast<NumberParsingState>("\7\7\4\4\7\7\7"[state]);
+
1069  /*
+
1070  if (state == NumberParsingState::Digits || state == NumberParsingState::ZeroFirst)
+
1071  {
+
1072  state = NumberParsingState::DigitsAfterPoints;
+
1073  }
+
1074  else
+
1075  return {};
+
1076  */
+
1077  break;
+
1078  case '-':
+
1079  state = static_cast<NumberParsingState>("\1\7\7\7\7\6\7"[state]);
+
1080  /*if (state == NumberParsingState::Minus)
+
1081  {
+
1082  state = NumberParsingState::AfterMinus;
+
1083  }
+
1084  else if (state == NumberParsingState::E)
+
1085  {
+
1086  state = NumberParsingState::DigitsAfterE;
+
1087  }
+
1088  else
+
1089  return {};*/
+
1090  break;
+
1091  case '+':
+
1092  state = static_cast<NumberParsingState>("\7\7\7\7\7\6\7"[state]);
+
1093  /*if (state == NumberParsingState::E)
+
1094  {
+
1095  state = NumberParsingState::DigitsAfterE;
+
1096  }
+
1097  else
+
1098  return {};*/
+
1099  break;
+
1100  case 'e':
+
1101  case 'E':
+
1102  state = static_cast<NumberParsingState>("\7\7\7\5\5\7\7"[state]);
+
1103  /*if (state == NumberParsingState::Digits ||
+
1104  state == NumberParsingState::DigitsAfterPoints)
+
1105  {
+
1106  state = NumberParsingState::E;
+
1107  }
+
1108  else
+
1109  return {};*/
+
1110  break;
+
1111  default:
+
1112  if (CROW_LIKELY(state == NumberParsingState::ZeroFirst ||
+
1113  state == NumberParsingState::Digits ||
+
1114  state == NumberParsingState::DigitsAfterPoints ||
+
1115  state == NumberParsingState::DigitsAfterE))
+
1116  return {type::Number, start, data};
+
1117  else
+
1118  return {};
+
1119  }
+
1120  data++;
+
1121  }
+
1122 
+
1123  return {};
+
1124  }
+
1125 
+
1126 
+
1127  rvalue decode_value(unsigned depth)
+
1128  {
+
1129  switch (*data)
+
1130  {
+
1131  case '[':
+
1132  return decode_list(depth + 1);
+
1133  case '{':
+
1134  return decode_object(depth + 1);
+
1135  case '"':
+
1136  return decode_string();
+
1137  case 't':
+
1138  if ( //e-data >= 4 &&
+
1139  data[1] == 'r' &&
+
1140  data[2] == 'u' &&
+
1141  data[3] == 'e')
+
1142  {
+
1143  data += 4;
+
1144  return {type::True};
+
1145  }
+
1146  else
+
1147  return {};
+
1148  case 'f':
+
1149  if ( //e-data >= 5 &&
+
1150  data[1] == 'a' &&
+
1151  data[2] == 'l' &&
+
1152  data[3] == 's' &&
+
1153  data[4] == 'e')
+
1154  {
+
1155  data += 5;
+
1156  return {type::False};
+
1157  }
+
1158  else
+
1159  return {};
+
1160  case 'n':
+
1161  if ( //e-data >= 4 &&
+
1162  data[1] == 'u' &&
+
1163  data[2] == 'l' &&
+
1164  data[3] == 'l')
+
1165  {
+
1166  data += 4;
+
1167  return {type::Null};
+
1168  }
+
1169  else
+
1170  return {};
+
1171  //case '1': case '2': case '3':
+
1172  //case '4': case '5': case '6':
+
1173  //case '7': case '8': case '9':
+
1174  //case '0': case '-':
+
1175  default:
+
1176  return decode_number();
+
1177  }
+
1178  return {};
+
1179  }
+
1180 
+
1181  rvalue decode_object(unsigned depth)
+
1182  {
+
1183  rvalue ret(type::Object);
+
1184  if (CROW_UNLIKELY(!consume('{')) || CROW_UNLIKELY(depth > max_depth))
+
1185  {
+
1186  ret.set_error();
+
1187  return ret;
+
1188  }
+
1189 
+
1190  ws_skip();
+
1191 
+
1192  if (CROW_UNLIKELY(*data == '}'))
+
1193  {
+
1194  data++;
+
1195  return ret;
+
1196  }
+
1197 
+
1198  while (1)
+
1199  {
+
1200  auto t = decode_string();
+
1201  if (CROW_UNLIKELY(!t))
+
1202  {
+
1203  ret.set_error();
+
1204  break;
+
1205  }
+
1206 
+
1207  ws_skip();
+
1208  if (CROW_UNLIKELY(!consume(':')))
+
1209  {
+
1210  ret.set_error();
+
1211  break;
+
1212  }
+
1213 
+
1214  // TODO(ipkn) caching key to speed up (flyweight?)
+
1215  // I have no idea how flyweight could apply here, but maybe some speedup can happen if we stopped checking type since decode_string returns a string anyway
+
1216  auto key = t.s();
+
1217 
+
1218  ws_skip();
+
1219  auto v = decode_value(depth + 1);
+
1220  if (CROW_UNLIKELY(!v))
+
1221  {
+
1222  ret.set_error();
+
1223  break;
+
1224  }
+
1225  ws_skip();
+
1226 
+
1227  v.key_ = std::move(key);
+
1228  ret.emplace_back(std::move(v));
+
1229  if (CROW_UNLIKELY(*data == '}'))
+
1230  {
+
1231  data++;
+
1232  break;
+
1233  }
+
1234  if (CROW_UNLIKELY(!consume(',')))
+
1235  {
+
1236  ret.set_error();
+
1237  break;
+
1238  }
+
1239  ws_skip();
+
1240  }
+
1241  return ret;
+
1242  }
+
1243 
+
1244  rvalue parse()
+
1245  {
+
1246  ws_skip();
+
1247  auto ret = decode_value(0); // or decode object?
+
1248  ws_skip();
+
1249  if (ret && *data != '\0')
+
1250  ret.set_error();
+
1251  return ret;
+
1252  }
+
1253 
+
1254  char* data;
+
1255  };
+
1256  return Parser(data, size).parse();
+
1257  }
+
1258  inline rvalue load(const char* data, size_t size)
+
1259  {
+
1260  char* s = new char[size + 1];
+
1261  memcpy(s, data, size);
+
1262  s[size] = 0;
+
1263  auto ret = load_nocopy_internal(s, size);
+
1264  if (ret)
+
1265  ret.key_.force(s, size);
+
1266  else
+
1267  delete[] s;
+
1268  return ret;
+
1269  }
+
1270 
+
1271  inline rvalue load(const char* data)
+
1272  {
+
1273  return load(data, strlen(data));
+
1274  }
+
1275 
+
1276  inline rvalue load(const std::string& str)
+
1277  {
+
1278  return load(str.data(), str.size());
+
1279  }
+
1280 
+
1281  struct wvalue_reader;
+
1282 
+
1283  /// JSON write value.
+
1284 
+
1285  ///
+
1286  /// Value can mean any json value, including a JSON object.<br>
+
1287  /// Write means this class is used to primarily assemble JSON objects using keys and values and export those into a string.
+
1288  class wvalue : public returnable
+
1289  {
+
1290  friend class crow::mustache::template_t;
+
1291  friend struct wvalue_reader;
+
1292 
+
1293  public:
+
1294  using object =
+
1295 #ifdef CROW_JSON_USE_MAP
+
1296  std::map<std::string, wvalue>;
+
1297 #else
+
1298  std::unordered_map<std::string, wvalue>;
+
1299 #endif
+
1300 
+
1301  using list = std::vector<wvalue>;
+
1302 
+
1303  type t() const { return t_; }
+
1304 
+
1305  /// Create an empty json value (outputs "{}" instead of a "null" string)
+
1306  static crow::json::wvalue empty_object() { return crow::json::wvalue::object(); }
+
1307 
+
1308  private:
+
1309  type t_{type::Null}; ///< The type of the value.
+
1310  num_type nt{num_type::Null}; ///< The specific type of the number if \ref t_ is a number.
+
1311  union number
+
1312  {
+
1313  double d;
+
1314  int64_t si;
+
1315  uint64_t ui;
+
1316 
+
1317  public:
+
1318  constexpr number() noexcept:
+
1319  ui() {} /* default constructor initializes unsigned integer. */
+
1320  constexpr number(std::uint64_t value) noexcept:
+
1321  ui(value) {}
+
1322  constexpr number(std::int64_t value) noexcept:
+
1323  si(value) {}
+
1324  explicit constexpr number(double value) noexcept:
+
1325  d(value) {}
+
1326  explicit constexpr number(float value) noexcept:
+
1327  d(value) {}
+
1328  } num; ///< Value if type is a number.
+
1329  std::string s; ///< Value if type is a string.
+
1330  std::unique_ptr<list> l; ///< Value if type is a list.
+
1331  std::unique_ptr<object> o; ///< Value if type is a JSON object.
+
1332  std::function<std::string(std::string&)> f; ///< Value if type is a function (C++ lambda)
+
1333 
+
1334  public:
+
1335  wvalue():
+
1336  returnable("application/json") {}
+
1337 
+
1338  wvalue(std::nullptr_t):
+
1339  returnable("application/json"), t_(type::Null) {}
+
1340 
+
1341  wvalue(bool value):
+
1342  returnable("application/json"), t_(value ? type::True : type::False) {}
+
1343 
+
1344  wvalue(std::uint8_t value):
+
1345  returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
+
1346  wvalue(std::uint16_t value):
+
1347  returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
+
1348  wvalue(std::uint32_t value):
+
1349  returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
+
1350  wvalue(std::uint64_t value):
+
1351  returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
+
1352 
+
1353  wvalue(std::int8_t value):
+
1354  returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
+
1355  wvalue(std::int16_t value):
+
1356  returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
+
1357  wvalue(std::int32_t value):
+
1358  returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
+
1359  wvalue(std::int64_t value):
+
1360  returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
+
1361 
+
1362  wvalue(float value):
+
1363  returnable("application/json"), t_(type::Number), nt(num_type::Floating_point), num(static_cast<double>(value)) {}
+
1364  wvalue(double value):
+
1365  returnable("application/json"), t_(type::Number), nt(num_type::Double_precision_floating_point), num(static_cast<double>(value)) {}
+
1366 
+
1367  wvalue(char const* value):
+
1368  returnable("application/json"), t_(type::String), s(value) {}
+
1369 
+
1370  wvalue(std::string const& value):
+
1371  returnable("application/json"), t_(type::String), s(value) {}
+
1372  wvalue(std::string&& value):
+
1373  returnable("application/json"), t_(type::String), s(std::move(value)) {}
+
1374 
+
1375  wvalue(std::initializer_list<std::pair<std::string const, wvalue>> initializer_list):
+
1376  returnable("application/json"), t_(type::Object), o(new object(initializer_list)) {}
+
1377 
+
1378  wvalue(object const& value):
+
1379  returnable("application/json"), t_(type::Object), o(new object(value)) {}
+
1380  wvalue(object&& value):
+
1381  returnable("application/json"), t_(type::Object), o(new object(std::move(value))) {}
+
1382 
+
1383  wvalue(const list& r):
+
1384  returnable("application/json")
+
1385  {
+
1386  t_ = type::List;
+
1387  l = std::unique_ptr<list>(new list{});
+
1388  l->reserve(r.size());
+
1389  for (auto it = r.begin(); it != r.end(); ++it)
+
1390  l->emplace_back(*it);
+
1391  }
+
1392  wvalue(list& r):
+
1393  returnable("application/json")
+
1394  {
+
1395  t_ = type::List;
+
1396  l = std::unique_ptr<list>(new list{});
+
1397  l->reserve(r.size());
+
1398  for (auto it = r.begin(); it != r.end(); ++it)
+
1399  l->emplace_back(*it);
+
1400  }
+
1401 
+
1402  /// Create a write value from a read value (useful for editing JSON strings).
+
1403  wvalue(const rvalue& r):
+
1404  returnable("application/json")
+
1405  {
+
1406  t_ = r.t();
+
1407  switch (r.t())
+
1408  {
+
1409  case type::Null:
+
1410  case type::False:
+
1411  case type::True:
+
1412  case type::Function:
+
1413  return;
+
1414  case type::Number:
+
1415  nt = r.nt();
+
1416  if (nt == num_type::Floating_point || nt == num_type::Double_precision_floating_point)
+
1417  num.d = r.d();
+
1418  else if (nt == num_type::Signed_integer)
+
1419  num.si = r.i();
+
1420  else
+
1421  num.ui = r.u();
+
1422  return;
+
1423  case type::String:
+
1424  s = r.s();
+
1425  return;
+
1426  case type::List:
+
1427  l = std::unique_ptr<list>(new list{});
+
1428  l->reserve(r.size());
+
1429  for (auto it = r.begin(); it != r.end(); ++it)
+
1430  l->emplace_back(*it);
+
1431  return;
+
1432  case type::Object:
+
1433  o = std::unique_ptr<object>(new object{});
+
1434  for (auto it = r.begin(); it != r.end(); ++it)
+
1435  o->emplace(it->key(), *it);
+
1436  return;
+
1437  }
+
1438  }
+
1439 
+
1440  wvalue(const wvalue& r):
+
1441  returnable("application/json")
+
1442  {
+
1443  t_ = r.t();
+
1444  switch (r.t())
+
1445  {
+
1446  case type::Null:
+
1447  case type::False:
+
1448  case type::True:
+
1449  return;
+
1450  case type::Number:
+
1451  nt = r.nt;
+
1452  if (nt == num_type::Floating_point || nt == num_type::Double_precision_floating_point)
+
1453  num.d = r.num.d;
+
1454  else if (nt == num_type::Signed_integer)
+
1455  num.si = r.num.si;
+
1456  else
+
1457  num.ui = r.num.ui;
+
1458  return;
+
1459  case type::String:
+
1460  s = r.s;
+
1461  return;
+
1462  case type::List:
+
1463  l = std::unique_ptr<list>(new list{});
+
1464  l->reserve(r.size());
+
1465  for (auto it = r.l->begin(); it != r.l->end(); ++it)
+
1466  l->emplace_back(*it);
+
1467  return;
+
1468  case type::Object:
+
1469  o = std::unique_ptr<object>(new object{});
+
1470  o->insert(r.o->begin(), r.o->end());
+
1471  return;
+
1472  case type::Function:
+
1473  f = r.f;
+
1474  }
+
1475  }
+
1476 
+
1477  wvalue(wvalue&& r):
+
1478  returnable("application/json")
+
1479  {
+
1480  *this = std::move(r);
+
1481  }
+
1482 
+
1483  wvalue& operator=(wvalue&& r)
+
1484  {
+
1485  t_ = r.t_;
+
1486  nt = r.nt;
+
1487  num = r.num;
+
1488  s = std::move(r.s);
+
1489  l = std::move(r.l);
+
1490  o = std::move(r.o);
+
1491  return *this;
+
1492  }
+
1493 
+
1494  /// Used for compatibility, same as \ref reset()
+
1495  void clear()
+
1496  {
+
1497  reset();
+
1498  }
+
1499 
+
1500  void reset()
+
1501  {
+
1502  t_ = type::Null;
+
1503  l.reset();
+
1504  o.reset();
+
1505  }
+
1506 
+
1507  wvalue& operator=(std::nullptr_t)
+
1508  {
+
1509  reset();
+
1510  return *this;
+
1511  }
+
1512  wvalue& operator=(bool value)
+
1513  {
+
1514  reset();
+
1515  if (value)
+
1516  t_ = type::True;
+
1517  else
+
1518  t_ = type::False;
+
1519  return *this;
+
1520  }
+
1521 
+
1522  wvalue& operator=(float value)
+
1523  {
+
1524  reset();
+
1525  t_ = type::Number;
+
1526  num.d = value;
+
1527  nt = num_type::Floating_point;
+
1528  return *this;
+
1529  }
+
1530 
+
1531  wvalue& operator=(double value)
+
1532  {
+
1533  reset();
+
1534  t_ = type::Number;
+
1535  num.d = value;
+
1536  nt = num_type::Double_precision_floating_point;
+
1537  return *this;
+
1538  }
+
1539 
+
1540  wvalue& operator=(unsigned short value)
+
1541  {
+
1542  reset();
+
1543  t_ = type::Number;
+
1544  num.ui = value;
+
1545  nt = num_type::Unsigned_integer;
+
1546  return *this;
+
1547  }
+
1548 
+
1549  wvalue& operator=(short value)
+
1550  {
+
1551  reset();
+
1552  t_ = type::Number;
+
1553  num.si = value;
+
1554  nt = num_type::Signed_integer;
+
1555  return *this;
+
1556  }
+
1557 
+
1558  wvalue& operator=(long long value)
+
1559  {
+
1560  reset();
+
1561  t_ = type::Number;
+
1562  num.si = value;
+
1563  nt = num_type::Signed_integer;
+
1564  return *this;
+
1565  }
+
1566 
+
1567  wvalue& operator=(long value)
+
1568  {
+
1569  reset();
+
1570  t_ = type::Number;
+
1571  num.si = value;
+
1572  nt = num_type::Signed_integer;
+
1573  return *this;
+
1574  }
+
1575 
+
1576  wvalue& operator=(int value)
+
1577  {
+
1578  reset();
+
1579  t_ = type::Number;
+
1580  num.si = value;
+
1581  nt = num_type::Signed_integer;
+
1582  return *this;
+
1583  }
+
1584 
+
1585  wvalue& operator=(unsigned long long value)
+
1586  {
+
1587  reset();
+
1588  t_ = type::Number;
+
1589  num.ui = value;
+
1590  nt = num_type::Unsigned_integer;
+
1591  return *this;
+
1592  }
+
1593 
+
1594  wvalue& operator=(unsigned long value)
+
1595  {
+
1596  reset();
+
1597  t_ = type::Number;
+
1598  num.ui = value;
+
1599  nt = num_type::Unsigned_integer;
+
1600  return *this;
+
1601  }
+
1602 
+
1603  wvalue& operator=(unsigned int value)
+
1604  {
+
1605  reset();
+
1606  t_ = type::Number;
+
1607  num.ui = value;
+
1608  nt = num_type::Unsigned_integer;
+
1609  return *this;
+
1610  }
+
1611 
+
1612  wvalue& operator=(const char* str)
+
1613  {
+
1614  reset();
+
1615  t_ = type::String;
+
1616  s = str;
+
1617  return *this;
+
1618  }
+
1619 
+
1620  wvalue& operator=(const std::string& str)
+
1621  {
+
1622  reset();
+
1623  t_ = type::String;
+
1624  s = str;
+
1625  return *this;
+
1626  }
+
1627 
+
1628  wvalue& operator=(list&& v)
+
1629  {
+
1630  if (t_ != type::List)
+
1631  reset();
+
1632  t_ = type::List;
+
1633  if (!l)
+
1634  l = std::unique_ptr<list>(new list{});
+
1635  l->clear();
+
1636  l->resize(v.size());
+
1637  size_t idx = 0;
+
1638  for (auto& x : v)
+
1639  {
+
1640  (*l)[idx++] = std::move(x);
+
1641  }
+
1642  return *this;
+
1643  }
+
1644 
+
1645  template<typename T>
+
1646  wvalue& operator=(const std::vector<T>& v)
+
1647  {
+
1648  if (t_ != type::List)
+
1649  reset();
+
1650  t_ = type::List;
+
1651  if (!l)
+
1652  l = std::unique_ptr<list>(new list{});
+
1653  l->clear();
+
1654  l->resize(v.size());
+
1655  size_t idx = 0;
+
1656  for (auto& x : v)
+
1657  {
+
1658  (*l)[idx++] = x;
+
1659  }
+
1660  return *this;
+
1661  }
+
1662 
+
1663  wvalue& operator=(std::initializer_list<std::pair<std::string const, wvalue>> initializer_list)
+
1664  {
+
1665  if (t_ != type::Object)
+
1666  {
+
1667  reset();
+
1668  t_ = type::Object;
+
1669  o = std::unique_ptr<object>(new object(initializer_list));
+
1670  }
+
1671  else
+
1672  {
+
1673 #if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__ANDROID__) || defined(_LIBCPP_VERSION)
+
1674  o = std::unique_ptr<object>(new object(initializer_list));
+
1675 #else
+
1676  (*o) = initializer_list;
+
1677 #endif
+
1678  }
+
1679  return *this;
+
1680  }
+
1681 
+
1682  wvalue& operator=(object const& value)
+
1683  {
+
1684  if (t_ != type::Object)
+
1685  {
+
1686  reset();
+
1687  t_ = type::Object;
+
1688  o = std::unique_ptr<object>(new object(value));
+
1689  }
+
1690  else
+
1691  {
+
1692 #if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__ANDROID__) || defined(_LIBCPP_VERSION)
+
1693  o = std::unique_ptr<object>(new object(value));
+
1694 #else
+
1695  (*o) = value;
+
1696 #endif
+
1697  }
+
1698  return *this;
+
1699  }
+
1700 
+
1701  wvalue& operator=(object&& value)
+
1702  {
+
1703  if (t_ != type::Object)
+
1704  {
+
1705  reset();
+
1706  t_ = type::Object;
+
1707  o = std::unique_ptr<object>(new object(std::move(value)));
+
1708  }
+
1709  else
+
1710  {
+
1711  (*o) = std::move(value);
+
1712  }
+
1713  return *this;
+
1714  }
+
1715 
+
1716  wvalue& operator=(std::function<std::string(std::string&)>&& func)
+
1717  {
+
1718  reset();
+
1719  t_ = type::Function;
+
1720  f = std::move(func);
+
1721  return *this;
+
1722  }
+
1723 
+
1724  wvalue& operator[](unsigned index)
+
1725  {
+
1726  if (t_ != type::List)
+
1727  reset();
+
1728  t_ = type::List;
+
1729  if (!l)
+
1730  l = std::unique_ptr<list>(new list{});
+
1731  if (l->size() < index + 1)
+
1732  l->resize(index + 1);
+
1733  return (*l)[index];
+
1734  }
+
1735 
+
1736  const wvalue& operator[](unsigned index) const
+
1737  {
+
1738  return const_cast<wvalue*>(this)->operator[](index);
+
1739  }
+
1740 
+
1741  int count(const std::string& str) const
+
1742  {
+
1743  if (t_ != type::Object)
+
1744  return 0;
+
1745  if (!o)
+
1746  return 0;
+
1747  return o->count(str);
+
1748  }
+
1749 
+
1750  wvalue& operator[](const std::string& str)
+
1751  {
+
1752  if (t_ != type::Object)
+
1753  reset();
+
1754  t_ = type::Object;
+
1755  if (!o)
+
1756  o = std::unique_ptr<object>(new object{});
+
1757  return (*o)[str];
+
1758  }
+
1759 
+
1760  const wvalue& operator[](const std::string& str) const
+
1761  {
+
1762  return const_cast<wvalue*>(this)->operator[](str);
+
1763  }
+
1764 
+
1765  std::vector<std::string> keys() const
+
1766  {
+
1767  if (t_ != type::Object)
+
1768  return {};
+
1769  std::vector<std::string> result;
+
1770  for (auto& kv : *o)
+
1771  {
+
1772  result.push_back(kv.first);
+
1773  }
+
1774  return result;
+
1775  }
+
1776 
+
1777  std::string execute(std::string txt = "") const //Not using reference because it cannot be used with a default rvalue
+
1778  {
+
1779  if (t_ != type::Function)
+
1780  return "";
+
1781  return f(txt);
+
1782  }
+
1783 
+
1784  /// If the wvalue is a list, it returns the length of the list, otherwise it returns 1.
+
1785  std::size_t size() const
+
1786  {
+
1787  if (t_ != type::List)
+
1788  return 1;
+
1789  return l->size();
+
1790  }
+
1791 
+
1792  /// Returns an estimated size of the value in bytes.
+
1793  size_t estimate_length() const
+
1794  {
+
1795  switch (t_)
+
1796  {
+
1797  case type::Null: return 4;
+
1798  case type::False: return 5;
+
1799  case type::True: return 4;
+
1800  case type::Number: return 30;
+
1801  case type::String: return 2 + s.size() + s.size() / 2;
+
1802  case type::List:
+
1803  {
+
1804  size_t sum{};
+
1805  if (l)
+
1806  {
+
1807  for (auto& x : *l)
+
1808  {
+
1809  sum += 1;
+
1810  sum += x.estimate_length();
+
1811  }
+
1812  }
+
1813  return sum + 2;
+
1814  }
+
1815  case type::Object:
+
1816  {
+
1817  size_t sum{};
+
1818  if (o)
+
1819  {
+
1820  for (auto& kv : *o)
+
1821  {
+
1822  sum += 2;
+
1823  sum += 2 + kv.first.size() + kv.first.size() / 2;
+
1824  sum += kv.second.estimate_length();
+
1825  }
+
1826  }
+
1827  return sum + 2;
+
1828  }
+
1829  case type::Function:
+
1830  return 0;
+
1831  }
+
1832  return 1;
+
1833  }
+
1834 
+
1835  private:
+
1836  inline void dump_string(const std::string& str, std::string& out) const
+
1837  {
+
1838  out.push_back('"');
+
1839  escape(str, out);
+
1840  out.push_back('"');
+
1841  }
+
1842 
+
1843  inline void dump_indentation_part(std::string& out, const int indent, const char separator, const int indent_level) const
+
1844  {
+
1845  out.push_back('\n');
+
1846  out.append(indent_level * indent, separator);
+
1847  }
+
1848 
+
1849 
+
1850  inline void dump_internal(const wvalue& v, std::string& out, const int indent, const char separator, const int indent_level = 0) const
+
1851  {
+
1852  switch (v.t_)
+
1853  {
+
1854  case type::Null: out += "null"; break;
+
1855  case type::False: out += "false"; break;
+
1856  case type::True: out += "true"; break;
+
1857  case type::Number:
+
1858  {
+
1859  if (v.nt == num_type::Floating_point || v.nt == num_type::Double_precision_floating_point)
+
1860  {
+
1861  if (isnan(v.num.d) || isinf(v.num.d))
+
1862  {
+
1863  out += "null";
+
1864  CROW_LOG_WARNING << "Invalid JSON value detected (" << v.num.d << "), value set to null";
+
1865  break;
+
1866  }
+
1867  enum
+
1868  {
+
1869  start,
+
1870  decp, // Decimal point
+
1871  zero
+
1872  } f_state;
+
1873  char outbuf[128];
+
1874  if (v.nt == num_type::Double_precision_floating_point)
+
1875  {
+
1876 #ifdef _MSC_VER
+
1877  sprintf_s(outbuf, sizeof(outbuf), "%.*g", DECIMAL_DIG, v.num.d);
+
1878 #else
+
1879  snprintf(outbuf, sizeof(outbuf), "%.*g", DECIMAL_DIG, v.num.d);
+
1880 #endif
+
1881  }
+
1882  else
+
1883  {
+
1884 #ifdef _MSC_VER
+
1885  sprintf_s(outbuf, sizeof(outbuf), "%f", v.num.d);
+
1886 #else
+
1887  snprintf(outbuf, sizeof(outbuf), "%f", v.num.d);
+
1888 #endif
+
1889  }
+
1890  char *p = &outbuf[0], *o = nullptr; // o is the position of the first trailing 0
+
1891  f_state = start;
+
1892  while (*p != '\0')
+
1893  {
+
1894  //std::cout << *p << std::endl;
+
1895  char ch = *p;
+
1896  switch (f_state)
+
1897  {
+
1898  case start: // Loop and lookahead until a decimal point is found
+
1899  if (ch == '.')
+
1900  {
+
1901  char fch = *(p + 1);
+
1902  // if the first character is 0, leave it be (this is so that "1.00000" becomes "1.0" and not "1.")
+
1903  if (fch != '\0' && fch == '0') p++;
+
1904  f_state = decp;
+
1905  }
+
1906  p++;
+
1907  break;
+
1908  case decp: // Loop until a 0 is found, if found, record its position
+
1909  if (ch == '0')
+
1910  {
+
1911  f_state = zero;
+
1912  o = p;
+
1913  }
+
1914  p++;
+
1915  break;
+
1916  case zero: // if a non 0 is found (e.g. 1.00004) remove the earlier recorded 0 position and look for more trailing 0s
+
1917  if (ch != '0')
+
1918  {
+
1919  o = nullptr;
+
1920  f_state = decp;
+
1921  }
+
1922  p++;
+
1923  break;
+
1924  }
+
1925  }
+
1926  if (o != nullptr) // if any trailing 0s are found, terminate the string where they begin
+
1927  *o = '\0';
+
1928  out += outbuf;
+
1929  }
+
1930  else if (v.nt == num_type::Signed_integer)
+
1931  {
+
1932  out += std::to_string(v.num.si);
+
1933  }
+
1934  else
+
1935  {
+
1936  out += std::to_string(v.num.ui);
+
1937  }
+
1938  }
+
1939  break;
+
1940  case type::String: dump_string(v.s, out); break;
+
1941  case type::List:
+
1942  {
+
1943  out.push_back('[');
+
1944 
+
1945  if (indent >= 0)
+
1946  {
+
1947  dump_indentation_part(out, indent, separator, indent_level + 1);
+
1948  }
+
1949 
+
1950  if (v.l)
+
1951  {
+
1952  bool first = true;
+
1953  for (auto& x : *v.l)
+
1954  {
+
1955  if (!first)
+
1956  {
+
1957  out.push_back(',');
+
1958 
+
1959  if (indent >= 0)
+
1960  {
+
1961  dump_indentation_part(out, indent, separator, indent_level + 1);
+
1962  }
+
1963  }
+
1964  first = false;
+
1965  dump_internal(x, out, indent, separator, indent_level + 1);
+
1966  }
+
1967  }
+
1968 
+
1969  if (indent >= 0)
+
1970  {
+
1971  dump_indentation_part(out, indent, separator, indent_level);
+
1972  }
+
1973 
+
1974  out.push_back(']');
+
1975  }
+
1976  break;
+
1977  case type::Object:
+
1978  {
+
1979  out.push_back('{');
+
1980 
+
1981  if (indent >= 0)
+
1982  {
+
1983  dump_indentation_part(out, indent, separator, indent_level + 1);
+
1984  }
+
1985 
+
1986  if (v.o)
+
1987  {
+
1988  bool first = true;
+
1989  for (auto& kv : *v.o)
+
1990  {
+
1991  if (!first)
+
1992  {
+
1993  out.push_back(',');
+
1994  if (indent >= 0)
+
1995  {
+
1996  dump_indentation_part(out, indent, separator, indent_level + 1);
+
1997  }
+
1998  }
+
1999  first = false;
+
2000  dump_string(kv.first, out);
+
2001  out.push_back(':');
+
2002 
+
2003  if (indent >= 0)
+
2004  {
+
2005  out.push_back(' ');
+
2006  }
+
2007 
+
2008  dump_internal(kv.second, out, indent, separator, indent_level + 1);
+
2009  }
+
2010  }
+
2011 
+
2012  if (indent >= 0)
+
2013  {
+
2014  dump_indentation_part(out, indent, separator, indent_level);
+
2015  }
+
2016 
+
2017  out.push_back('}');
+
2018  }
+
2019  break;
+
2020 
+
2021  case type::Function:
+
2022  out += "custom function";
+
2023  break;
+
2024  }
+
2025  }
+
2026 
+
2027  public:
+
2028  std::string dump(const int indent, const char separator = ' ') const
+
2029  {
+
2030  std::string ret;
+
2031  ret.reserve(estimate_length());
+
2032  dump_internal(*this, ret, indent, separator);
+
2033  return ret;
+
2034  }
+
2035 
+
2036  std::string dump() const
+
2037  {
+
2038  static constexpr int DontIndent = -1;
+
2039 
+
2040  return dump(DontIndent);
+
2041  }
+
2042  };
+
2043 
+
2044  // Used for accessing the internals of a wvalue
+ +
2046  {
+
2047  int64_t get(int64_t fallback)
+
2048  {
+
2049  if (ref.t() != type::Number || ref.nt == num_type::Floating_point ||
+
2050  ref.nt == num_type::Double_precision_floating_point)
+
2051  return fallback;
+
2052  return ref.num.si;
+
2053  }
+
2054 
+
2055  double get(double fallback)
+
2056  {
+
2057  if (ref.t() != type::Number || ref.nt != num_type::Floating_point ||
+
2058  ref.nt == num_type::Double_precision_floating_point)
+
2059  return fallback;
+
2060  return ref.num.d;
+
2061  }
+
2062 
+
2063  bool get(bool fallback)
+
2064  {
+
2065  if (ref.t() == type::True) return true;
+
2066  if (ref.t() == type::False) return false;
+
2067  return fallback;
+
2068  }
+
2069 
+
2070  std::string get(const std::string& fallback)
+
2071  {
+
2072  if (ref.t() != type::String) return fallback;
+
2073  return ref.s;
+
2074  }
+
2075 
+
2076  const wvalue& ref;
+
2077  };
+
2078 
+
2079  //std::vector<asio::const_buffer> dump_ref(wvalue& v)
+
2080  //{
+
2081  //}
+
2082  } // namespace json
+
2083 } // namespace crow
+
JSON read value.
Definition: json.h:276
+
int64_t i() const
The integer value.
Definition: json.h:398
+
std::vector< rvalue > lo()
The list or object value.
Definition: json.h:462
+
bool has(const char *str) const
Check if the json object has the passed string as a key.
Definition: json.h:543
+
double d() const
The double precision floating-point number value.
Definition: json.h:431
+
bool b() const
The boolean value.
Definition: json.h:441
+
uint64_t u() const
The unsigned integer value.
Definition: json.h:415
+
void unescape() const
Convert escaped string character to their original form ("\\n" -> ' ').
Definition: json.h:478
+
num_type nt() const
The number type of the JSON value.
Definition: json.h:386
+
type t() const
The type of the JSON value.
Definition: json.h:374
+
detail::r_string s() const
The string value.
Definition: json.h:451
+
JSON write value.
Definition: json.h:1289
+
wvalue(const rvalue &r)
Create a write value from a read value (useful for editing JSON strings).
Definition: json.h:1403
+
std::size_t size() const
If the wvalue is a list, it returns the length of the list, otherwise it returns 1.
Definition: json.h:1785
+
size_t estimate_length() const
Returns an estimated size of the value in bytes.
Definition: json.h:1793
+
static crow::json::wvalue empty_object()
Create an empty json value (outputs "{}" instead of a "null" string)
Definition: json.h:1306
+
void clear()
Used for compatibility, same as reset()
Definition: json.h:1495
+
A mustache template object.
Definition: mustache.h:74
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
A read string implementation with comparison functionality.
Definition: json.h:120
+
char * s_
Start.
Definition: json.h:171
+
char * e_
End.
Definition: json.h:172
+
Definition: json.h:2046
+
An abstract class that allows any other class to be returned by a handler.
Definition: returnable.h:9
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/logging_8h_source.html b/1.2/reference/logging_8h_source.html new file mode 100644 index 000000000..2c07c7e76 --- /dev/null +++ b/1.2/reference/logging_8h_source.html @@ -0,0 +1,286 @@ + + + + + + + + Crow: include/crow/logging.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
logging.h
+
+
+
1 #pragma once
+
2 
+
3 #include "crow/settings.h"
+
4 
+
5 #include <cstdio>
+
6 #include <cstdlib>
+
7 #include <ctime>
+
8 #include <iostream>
+
9 #include <sstream>
+
10 #include <string>
+
11 
+
12 namespace crow
+
13 {
+
14  enum class LogLevel
+
15  {
+
16 #ifndef ERROR
+
17 #ifndef DEBUG
+
18  DEBUG = 0,
+
19  INFO,
+
20  WARNING,
+
21  ERROR,
+
22  CRITICAL,
+
23 #endif
+
24 #endif
+
25 
+
26  Debug = 0,
+
27  Info,
+
28  Warning,
+
29  Error,
+
30  Critical,
+
31  };
+
32 
+ +
34  {
+
35  public:
+
36  virtual ~ILogHandler() = default;
+
37 
+
38  virtual void log(std::string message, LogLevel level) = 0;
+
39  };
+
40 
+
41  class CerrLogHandler : public ILogHandler
+
42  {
+
43  public:
+
44  void log(std::string message, LogLevel level) override
+
45  {
+
46  std::string prefix;
+
47  switch (level)
+
48  {
+
49  case LogLevel::Debug:
+
50  prefix = "DEBUG ";
+
51  break;
+
52  case LogLevel::Info:
+
53  prefix = "INFO ";
+
54  break;
+
55  case LogLevel::Warning:
+
56  prefix = "WARNING ";
+
57  break;
+
58  case LogLevel::Error:
+
59  prefix = "ERROR ";
+
60  break;
+
61  case LogLevel::Critical:
+
62  prefix = "CRITICAL";
+
63  break;
+
64  }
+
65  std::cerr << std::string("(") + timestamp() + std::string(") [") + prefix + std::string("] ") + message << std::endl;
+
66  }
+
67 
+
68  private:
+
69  static std::string timestamp()
+
70  {
+
71  char date[32];
+
72  time_t t = time(0);
+
73 
+
74  tm my_tm;
+
75 
+
76 #if defined(_MSC_VER) || defined(__MINGW32__)
+
77 #ifdef CROW_USE_LOCALTIMEZONE
+
78  localtime_s(&my_tm, &t);
+
79 #else
+
80  gmtime_s(&my_tm, &t);
+
81 #endif
+
82 #else
+
83 #ifdef CROW_USE_LOCALTIMEZONE
+
84  localtime_r(&t, &my_tm);
+
85 #else
+
86  gmtime_r(&t, &my_tm);
+
87 #endif
+
88 #endif
+
89 
+
90  size_t sz = strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", &my_tm);
+
91  return std::string(date, date + sz);
+
92  }
+
93  };
+
94 
+
95  class logger
+
96  {
+
97  public:
+
98  logger(LogLevel level):
+
99  level_(level)
+
100  {}
+
101  ~logger()
+
102  {
+
103 #ifdef CROW_ENABLE_LOGGING
+
104  if (level_ >= get_current_log_level())
+
105  {
+
106  get_handler_ref()->log(stringstream_.str(), level_);
+
107  }
+
108 #endif
+
109  }
+
110 
+
111  //
+
112  template<typename T>
+
113  logger& operator<<(T const& value)
+
114  {
+
115 #ifdef CROW_ENABLE_LOGGING
+
116  if (level_ >= get_current_log_level())
+
117  {
+
118  stringstream_ << value;
+
119  }
+
120 #endif
+
121  return *this;
+
122  }
+
123 
+
124  //
+
125  static void setLogLevel(LogLevel level) { get_log_level_ref() = level; }
+
126 
+
127  static void setHandler(ILogHandler* handler) { get_handler_ref() = handler; }
+
128 
+
129  static LogLevel get_current_log_level() { return get_log_level_ref(); }
+
130 
+
131  private:
+
132  //
+
133  static LogLevel& get_log_level_ref()
+
134  {
+
135  static LogLevel current_level = static_cast<LogLevel>(CROW_LOG_LEVEL);
+
136  return current_level;
+
137  }
+
138  static ILogHandler*& get_handler_ref()
+
139  {
+
140  static CerrLogHandler default_handler;
+
141  static ILogHandler* current_handler = &default_handler;
+
142  return current_handler;
+
143  }
+
144 
+
145  //
+
146  std::ostringstream stringstream_;
+
147  LogLevel level_;
+
148  };
+
149 } // namespace crow
+
150 
+
151 #define CROW_LOG_CRITICAL \
+
152  if (crow::logger::get_current_log_level() <= crow::LogLevel::Critical) \
+
153  crow::logger(crow::LogLevel::Critical)
+
154 #define CROW_LOG_ERROR \
+
155  if (crow::logger::get_current_log_level() <= crow::LogLevel::Error) \
+
156  crow::logger(crow::LogLevel::Error)
+
157 #define CROW_LOG_WARNING \
+
158  if (crow::logger::get_current_log_level() <= crow::LogLevel::Warning) \
+
159  crow::logger(crow::LogLevel::Warning)
+
160 #define CROW_LOG_INFO \
+
161  if (crow::logger::get_current_log_level() <= crow::LogLevel::Info) \
+
162  crow::logger(crow::LogLevel::Info)
+
163 #define CROW_LOG_DEBUG \
+
164  if (crow::logger::get_current_log_level() <= crow::LogLevel::Debug) \
+
165  crow::logger(crow::LogLevel::Debug)
+
Definition: logging.h:42
+
Definition: logging.h:34
+
Definition: logging.h:96
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/logo55.png b/1.2/reference/logo55.png new file mode 100644 index 000000000..c6cd8bf58 Binary files /dev/null and b/1.2/reference/logo55.png differ diff --git a/1.2/reference/middleware_8h_source.html b/1.2/reference/middleware_8h_source.html new file mode 100644 index 000000000..ca646b290 --- /dev/null +++ b/1.2/reference/middleware_8h_source.html @@ -0,0 +1,468 @@ + + + + + + + + Crow: include/crow/middleware.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
middleware.h
+
+
+
1 #pragma once
+
2 
+
3 #include "crow/http_request.h"
+
4 #include "crow/http_response.h"
+
5 #include "crow/utility.h"
+
6 
+
7 #include <tuple>
+
8 #include <type_traits>
+
9 #include <iostream>
+
10 #include <utility>
+
11 
+
12 namespace crow // NOTE: Already documented in "crow/app.h"
+
13 {
+
14 
+
15  /// Local middleware should extend ILocalMiddleware
+ +
17  {
+
18  using call_global = std::false_type;
+
19  };
+
20 
+
21  namespace detail
+
22  {
+
23  template<typename MW>
+ +
25  {
+
26  template<typename T, void (T::*)(request&, response&, typename MW::context&) const = &T::before_handle>
+
27  struct get
+
28  {};
+
29  };
+
30 
+
31  template<typename MW>
+ +
33  {
+
34  template<typename T, void (T::*)(request&, response&, typename MW::context&) = &T::before_handle>
+
35  struct get
+
36  {};
+
37  };
+
38 
+
39  template<typename MW>
+ +
41  {
+
42  template<typename T, void (T::*)(request&, response&, typename MW::context&) const = &T::after_handle>
+
43  struct get
+
44  {};
+
45  };
+
46 
+
47  template<typename MW>
+ +
49  {
+
50  template<typename T, void (T::*)(request&, response&, typename MW::context&) = &T::after_handle>
+
51  struct get
+
52  {};
+
53  };
+
54 
+
55  template<typename MW>
+ +
57  {
+
58  template<typename T, typename std::enable_if<T::call_global::value == false, bool>::type = true>
+
59  struct get
+
60  {};
+
61  };
+
62 
+
63  template<typename T>
+ +
65  {
+
66  template<typename C>
+
67  static std::true_type f(typename check_before_handle_arity_3_const<T>::template get<C>*);
+
68 
+
69  template<typename C>
+
70  static std::true_type f(typename check_before_handle_arity_3<T>::template get<C>*);
+
71 
+
72  template<typename C>
+
73  static std::false_type f(...);
+
74 
+
75  public:
+
76  static const bool value = decltype(f<T>(nullptr))::value;
+
77  };
+
78 
+
79  template<typename T>
+ +
81  {
+
82  template<typename C>
+
83  static std::true_type f(typename check_after_handle_arity_3_const<T>::template get<C>*);
+
84 
+
85  template<typename C>
+
86  static std::true_type f(typename check_after_handle_arity_3<T>::template get<C>*);
+
87 
+
88  template<typename C>
+
89  static std::false_type f(...);
+
90 
+
91  public:
+
92  static constexpr bool value = decltype(f<T>(nullptr))::value;
+
93  };
+
94 
+
95  template<typename MW>
+ +
97  {
+
98  template<typename C>
+
99  static std::false_type f(typename check_global_call_false<MW>::template get<C>*);
+
100 
+
101  template<typename C>
+
102  static std::true_type f(...);
+
103 
+
104  static const bool value = decltype(f<MW>(nullptr))::value;
+
105  };
+
106 
+
107  template<typename MW, typename Context, typename ParentContext>
+
108  typename std::enable_if<!is_before_handle_arity_3_impl<MW>::value>::type
+
109  before_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/)
+
110  {
+
111  mw.before_handle(req, res, ctx.template get<MW>(), ctx);
+
112  }
+
113 
+
114  template<typename MW, typename Context, typename ParentContext>
+
115  typename std::enable_if<is_before_handle_arity_3_impl<MW>::value>::type
+
116  before_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/)
+
117  {
+
118  mw.before_handle(req, res, ctx.template get<MW>());
+
119  }
+
120 
+
121  template<typename MW, typename Context, typename ParentContext>
+
122  typename std::enable_if<!is_after_handle_arity_3_impl<MW>::value>::type
+
123  after_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/)
+
124  {
+
125  mw.after_handle(req, res, ctx.template get<MW>(), ctx);
+
126  }
+
127 
+
128  template<typename MW, typename Context, typename ParentContext>
+
129  typename std::enable_if<is_after_handle_arity_3_impl<MW>::value>::type
+
130  after_handler_call(MW& mw, request& req, response& res, Context& ctx, ParentContext& /*parent_ctx*/)
+
131  {
+
132  mw.after_handle(req, res, ctx.template get<MW>());
+
133  }
+
134 
+
135 
+
136  template<typename CallCriteria,
+
137  int N, typename Context, typename Container>
+
138  typename std::enable_if<(N < std::tuple_size<typename std::remove_reference<Container>::type>::value), bool>::type
+
139  middleware_call_helper(const CallCriteria& cc, Container& middlewares, request& req, response& res, Context& ctx)
+
140  {
+
141 
+
142  using CurrentMW = typename std::tuple_element<N, typename std::remove_reference<Container>::type>::type;
+
143 
+
144  if (!cc.template enabled<CurrentMW>(N))
+
145  {
+
146  return middleware_call_helper<CallCriteria, N + 1, Context, Container>(cc, middlewares, req, res, ctx);
+
147  }
+
148 
+
149  using parent_context_t = typename Context::template partial<N - 1>;
+
150  before_handler_call<CurrentMW, Context, parent_context_t>(std::get<N>(middlewares), req, res, ctx, static_cast<parent_context_t&>(ctx));
+
151  if (res.is_completed())
+
152  {
+
153  after_handler_call<CurrentMW, Context, parent_context_t>(std::get<N>(middlewares), req, res, ctx, static_cast<parent_context_t&>(ctx));
+
154  return true;
+
155  }
+
156 
+
157  if (middleware_call_helper<CallCriteria, N + 1, Context, Container>(cc, middlewares, req, res, ctx))
+
158  {
+
159  after_handler_call<CurrentMW, Context, parent_context_t>(std::get<N>(middlewares), req, res, ctx, static_cast<parent_context_t&>(ctx));
+
160  return true;
+
161  }
+
162 
+
163  return false;
+
164  }
+
165 
+
166  template<typename CallCriteria, int N, typename Context, typename Container>
+
167  typename std::enable_if<(N >= std::tuple_size<typename std::remove_reference<Container>::type>::value), bool>::type
+
168  middleware_call_helper(const CallCriteria& /*cc*/, Container& /*middlewares*/, request& /*req*/, response& /*res*/, Context& /*ctx*/)
+
169  {
+
170  return false;
+
171  }
+
172 
+
173  template<typename CallCriteria, int N, typename Context, typename Container>
+
174  typename std::enable_if<(N < 0)>::type
+
175  after_handlers_call_helper(const CallCriteria& /*cc*/, Container& /*middlewares*/, Context& /*context*/, request& /*req*/, response& /*res*/)
+
176  {
+
177  }
+
178 
+
179  template<typename CallCriteria, int N, typename Context, typename Container>
+
180  typename std::enable_if<(N == 0)>::type after_handlers_call_helper(const CallCriteria& cc, Container& middlewares, Context& ctx, request& req, response& res)
+
181  {
+
182  using parent_context_t = typename Context::template partial<N - 1>;
+
183  using CurrentMW = typename std::tuple_element<N, typename std::remove_reference<Container>::type>::type;
+
184  if (cc.template enabled<CurrentMW>(N))
+
185  {
+
186  after_handler_call<CurrentMW, Context, parent_context_t>(std::get<N>(middlewares), req, res, ctx, static_cast<parent_context_t&>(ctx));
+
187  }
+
188  }
+
189 
+
190  template<typename CallCriteria, int N, typename Context, typename Container>
+
191  typename std::enable_if<(N > 0)>::type after_handlers_call_helper(const CallCriteria& cc, Container& middlewares, Context& ctx, request& req, response& res)
+
192  {
+
193  using parent_context_t = typename Context::template partial<N - 1>;
+
194  using CurrentMW = typename std::tuple_element<N, typename std::remove_reference<Container>::type>::type;
+
195  if (cc.template enabled<CurrentMW>(N))
+
196  {
+
197  after_handler_call<CurrentMW, Context, parent_context_t>(std::get<N>(middlewares), req, res, ctx, static_cast<parent_context_t&>(ctx));
+
198  }
+
199  after_handlers_call_helper<CallCriteria, N - 1, Context, Container>(cc, middlewares, ctx, req, res);
+
200  }
+
201 
+
202  // A CallCriteria that accepts only global middleware
+ +
204  {
+
205  template<typename MW>
+
206  constexpr bool enabled(int) const
+
207  {
+ +
209  }
+
210  };
+
211 
+
212  template<typename F, typename... Args>
+
213  typename std::enable_if<black_magic::CallHelper<F, black_magic::S<Args...>>::value, void>::type
+
214  wrapped_handler_call(crow::request& /*req*/, crow::response& res, const F& f, Args&&... args)
+
215  {
+
216  static_assert(!std::is_same<void, decltype(f(std::declval<Args>()...))>::value,
+
217  "Handler function cannot have void return type; valid return types: string, int, crow::response, crow::returnable");
+
218 
+
219  res = crow::response(f(std::forward<Args>(args)...));
+
220  res.end();
+
221  }
+
222 
+
223  template<typename F, typename... Args>
+
224  typename std::enable_if<
+
225  !black_magic::CallHelper<F, black_magic::S<Args...>>::value &&
+
226  black_magic::CallHelper<F, black_magic::S<crow::request&, Args...>>::value,
+
227  void>::type
+
228  wrapped_handler_call(crow::request& req, crow::response& res, const F& f, Args&&... args)
+
229  {
+
230  static_assert(!std::is_same<void, decltype(f(std::declval<crow::request>(), std::declval<Args>()...))>::value,
+
231  "Handler function cannot have void return type; valid return types: string, int, crow::response, crow::returnable");
+
232 
+
233  res = crow::response(f(req, std::forward<Args>(args)...));
+
234  res.end();
+
235  }
+
236 
+
237  template<typename F, typename... Args>
+
238  typename std::enable_if<
+
239  !black_magic::CallHelper<F, black_magic::S<Args...>>::value &&
+
240  !black_magic::CallHelper<F, black_magic::S<crow::request&, Args...>>::value &&
+
241  black_magic::CallHelper<F, black_magic::S<crow::response&, Args...>>::value,
+
242  void>::type
+
243  wrapped_handler_call(crow::request& /*req*/, crow::response& res, const F& f, Args&&... args)
+
244  {
+
245  static_assert(std::is_same<void, decltype(f(std::declval<crow::response&>(), std::declval<Args>()...))>::value,
+
246  "Handler function with response argument should have void return type");
+
247 
+
248  f(res, std::forward<Args>(args)...);
+
249  }
+
250 
+
251  template<typename F, typename... Args>
+
252  typename std::enable_if<
+
253  !black_magic::CallHelper<F, black_magic::S<Args...>>::value &&
+
254  !black_magic::CallHelper<F, black_magic::S<crow::request&, Args...>>::value &&
+
255  !black_magic::CallHelper<F, black_magic::S<crow::response&, Args...>>::value &&
+
256  black_magic::CallHelper<F, black_magic::S<const crow::request&, crow::response&, Args...>>::value,
+
257  void>::type
+
258  wrapped_handler_call(crow::request& req, crow::response& res, const F& f, Args&&... args)
+
259  {
+
260  static_assert(std::is_same<void, decltype(f(std::declval<crow::request&>(), std::declval<crow::response&>(), std::declval<Args>()...))>::value,
+
261  "Handler function with response argument should have void return type");
+
262 
+
263  f(req, res, std::forward<Args>(args)...);
+
264  }
+
265 
+
266  // wrapped_handler_call transparently wraps a handler call behind (req, res, args...)
+
267  template<typename F, typename... Args>
+
268  typename std::enable_if<
+
269  !black_magic::CallHelper<F, black_magic::S<Args...>>::value &&
+
270  !black_magic::CallHelper<F, black_magic::S<crow::request&, Args...>>::value &&
+
271  !black_magic::CallHelper<F, black_magic::S<crow::response&, Args...>>::value &&
+
272  !black_magic::CallHelper<F, black_magic::S<const crow::request&, crow::response&, Args...>>::value,
+
273  void>::type
+
274  wrapped_handler_call(crow::request& req, crow::response& res, const F& f, Args&&... args)
+
275  {
+
276  static_assert(std::is_same<void, decltype(f(std::declval<crow::request&>(), std::declval<crow::response&>(), std::declval<Args>()...))>::value,
+
277  "Handler function with response argument should have void return type");
+
278 
+
279  f(req, res, std::forward<Args>(args)...);
+
280  }
+
281 
+
282  template<bool Reversed>
+ +
284  {};
+
285 
+
286  template<>
+ +
288  {
+
289  middleware_call_criteria_dynamic(const std::vector<int>& indices):
+
290  indices(indices), slider(0) {}
+
291 
+
292  template<typename>
+
293  bool enabled(int mw_index) const
+
294  {
+
295  if (slider < int(indices.size()) && indices[slider] == mw_index)
+
296  {
+
297  slider++;
+
298  return true;
+
299  }
+
300  return false;
+
301  }
+
302 
+
303  private:
+
304  const std::vector<int>& indices;
+
305  mutable int slider;
+
306  };
+
307 
+
308  template<>
+ +
310  {
+
311  middleware_call_criteria_dynamic(const std::vector<int>& indices):
+
312  indices(indices), slider(int(indices.size()) - 1) {}
+
313 
+
314  template<typename>
+
315  bool enabled(int mw_index) const
+
316  {
+
317  if (slider >= 0 && indices[slider] == mw_index)
+
318  {
+
319  slider--;
+
320  return true;
+
321  }
+
322  return false;
+
323  }
+
324 
+
325  private:
+
326  const std::vector<int>& indices;
+
327  mutable int slider;
+
328  };
+
329 
+
330  } // namespace detail
+
331 } // namespace crow
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
Local middleware should extend ILocalMiddleware.
Definition: middleware.h:17
+ + + +
Definition: middleware.h:49
+ + + + + +
Definition: middleware.h:57
+ + +
Definition: middleware.h:97
+ + +
An HTTP request.
Definition: http_request.h:36
+
HTTP response.
Definition: http_response.h:34
+
void end()
Set the response completion flag and call the handler (to send the response).
Definition: http_response.h:237
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/middleware__context_8h_source.html b/1.2/reference/middleware__context_8h_source.html new file mode 100644 index 000000000..356710e76 --- /dev/null +++ b/1.2/reference/middleware__context_8h_source.html @@ -0,0 +1,182 @@ + + + + + + + + Crow: include/crow/middleware_context.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
middleware_context.h
+
+
+
1 #pragma once
+
2 
+
3 #include "crow/utility.h"
+
4 #include "crow/http_request.h"
+
5 #include "crow/http_response.h"
+
6 
+
7 namespace crow
+
8 {
+
9  namespace detail
+
10  {
+
11 
+
12 
+
13  template<typename... Middlewares>
+
14  struct partial_context : public black_magic::pop_back<Middlewares...>::template rebind<partial_context>, public black_magic::last_element_type<Middlewares...>::type::context
+
15  {
+
16  using parent_context = typename black_magic::pop_back<Middlewares...>::template rebind<::crow::detail::partial_context>;
+
17  template<int N>
+
18  using partial = typename std::conditional<N == sizeof...(Middlewares) - 1, partial_context, typename parent_context::template partial<N>>::type;
+
19 
+
20  template<typename T>
+
21  typename T::context& get()
+
22  {
+
23  return static_cast<typename T::context&>(*this);
+
24  }
+
25  };
+
26 
+
27 
+
28 
+
29  template<>
+
30  struct partial_context<>
+
31  {
+
32  template<int>
+
33  using partial = partial_context;
+
34  };
+
35 
+
36 
+
37  template<typename... Middlewares>
+
38  struct context : private partial_context<Middlewares...>
+
39  //struct context : private Middlewares::context... // simple but less type-safe
+
40  {
+
41  template<typename CallCriteria, int N, typename Context, typename Container>
+
42  friend typename std::enable_if<(N == 0)>::type after_handlers_call_helper(const CallCriteria& cc, Container& middlewares, Context& ctx, request& req, response& res);
+
43  template<typename CallCriteria, int N, typename Context, typename Container>
+
44  friend typename std::enable_if<(N > 0)>::type after_handlers_call_helper(const CallCriteria& cc, Container& middlewares, Context& ctx, request& req, response& res);
+
45 
+
46  template<typename CallCriteria, int N, typename Context, typename Container>
+
47  friend typename std::enable_if<(N < std::tuple_size<typename std::remove_reference<Container>::type>::value), bool>::type
+
48  middleware_call_helper(const CallCriteria& cc, Container& middlewares, request& req, response& res, Context& ctx);
+
49 
+
50  template<typename T>
+
51  typename T::context& get()
+
52  {
+
53  return static_cast<typename T::context&>(*this);
+
54  }
+
55 
+
56  template<int N>
+
57  using partial = typename partial_context<Middlewares...>::template partial<N>;
+
58  };
+
59  } // namespace detail
+
60 } // namespace crow
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
Definition: middleware_context.h:40
+
Definition: middleware_context.h:15
+
An HTTP request.
Definition: http_request.h:36
+
HTTP response.
Definition: http_response.h:34
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/mime__types_8h_source.html b/1.2/reference/mime__types_8h_source.html new file mode 100644 index 000000000..fd771e60d --- /dev/null +++ b/1.2/reference/mime__types_8h_source.html @@ -0,0 +1,236 @@ + + + + + + + + Crow: include/crow/mime_types.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
mime_types.h
+
+
+
1 // This file is generated from nginx/conf/mime.types using nginx_mime2cpp.py on 2021-12-03.
+
2 #include <unordered_map>
+
3 #include <string>
+
4 
+
5 namespace crow
+
6 {
+
7  const std::unordered_map<std::string, std::string> mime_types{
+
8  {"shtml", "text/html"},
+
9  {"htm", "text/html"},
+
10  {"html", "text/html"},
+
11  {"css", "text/css"},
+
12  {"xml", "text/xml"},
+
13  {"gif", "image/gif"},
+
14  {"jpg", "image/jpeg"},
+
15  {"jpeg", "image/jpeg"},
+
16  {"js", "application/javascript"},
+
17  {"atom", "application/atom+xml"},
+
18  {"rss", "application/rss+xml"},
+
19  {"mml", "text/mathml"},
+
20  {"txt", "text/plain"},
+
21  {"jad", "text/vnd.sun.j2me.app-descriptor"},
+
22  {"wml", "text/vnd.wap.wml"},
+
23  {"htc", "text/x-component"},
+
24  {"avif", "image/avif"},
+
25  {"png", "image/png"},
+
26  {"svgz", "image/svg+xml"},
+
27  {"svg", "image/svg+xml"},
+
28  {"tiff", "image/tiff"},
+
29  {"tif", "image/tiff"},
+
30  {"wbmp", "image/vnd.wap.wbmp"},
+
31  {"webp", "image/webp"},
+
32  {"ico", "image/x-icon"},
+
33  {"jng", "image/x-jng"},
+
34  {"bmp", "image/x-ms-bmp"},
+
35  {"woff", "font/woff"},
+
36  {"woff2", "font/woff2"},
+
37  {"ear", "application/java-archive"},
+
38  {"war", "application/java-archive"},
+
39  {"jar", "application/java-archive"},
+
40  {"json", "application/json"},
+
41  {"hqx", "application/mac-binhex40"},
+
42  {"doc", "application/msword"},
+
43  {"pdf", "application/pdf"},
+
44  {"ai", "application/postscript"},
+
45  {"eps", "application/postscript"},
+
46  {"ps", "application/postscript"},
+
47  {"rtf", "application/rtf"},
+
48  {"m3u8", "application/vnd.apple.mpegurl"},
+
49  {"kml", "application/vnd.google-earth.kml+xml"},
+
50  {"kmz", "application/vnd.google-earth.kmz"},
+
51  {"xls", "application/vnd.ms-excel"},
+
52  {"eot", "application/vnd.ms-fontobject"},
+
53  {"ppt", "application/vnd.ms-powerpoint"},
+
54  {"odg", "application/vnd.oasis.opendocument.graphics"},
+
55  {"odp", "application/vnd.oasis.opendocument.presentation"},
+
56  {"ods", "application/vnd.oasis.opendocument.spreadsheet"},
+
57  {"odt", "application/vnd.oasis.opendocument.text"},
+
58  {"pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
+
59  {"xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
+
60  {"docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
+
61  {"wmlc", "application/vnd.wap.wmlc"},
+
62  {"wasm", "application/wasm"},
+
63  {"7z", "application/x-7z-compressed"},
+
64  {"cco", "application/x-cocoa"},
+
65  {"jardiff", "application/x-java-archive-diff"},
+
66  {"jnlp", "application/x-java-jnlp-file"},
+
67  {"run", "application/x-makeself"},
+
68  {"pm", "application/x-perl"},
+
69  {"pl", "application/x-perl"},
+
70  {"pdb", "application/x-pilot"},
+
71  {"prc", "application/x-pilot"},
+
72  {"rar", "application/x-rar-compressed"},
+
73  {"rpm", "application/x-redhat-package-manager"},
+
74  {"sea", "application/x-sea"},
+
75  {"swf", "application/x-shockwave-flash"},
+
76  {"sit", "application/x-stuffit"},
+
77  {"tk", "application/x-tcl"},
+
78  {"tcl", "application/x-tcl"},
+
79  {"crt", "application/x-x509-ca-cert"},
+
80  {"pem", "application/x-x509-ca-cert"},
+
81  {"der", "application/x-x509-ca-cert"},
+
82  {"xpi", "application/x-xpinstall"},
+
83  {"xhtml", "application/xhtml+xml"},
+
84  {"xspf", "application/xspf+xml"},
+
85  {"zip", "application/zip"},
+
86  {"dll", "application/octet-stream"},
+
87  {"exe", "application/octet-stream"},
+
88  {"bin", "application/octet-stream"},
+
89  {"deb", "application/octet-stream"},
+
90  {"dmg", "application/octet-stream"},
+
91  {"img", "application/octet-stream"},
+
92  {"iso", "application/octet-stream"},
+
93  {"msm", "application/octet-stream"},
+
94  {"msp", "application/octet-stream"},
+
95  {"msi", "application/octet-stream"},
+
96  {"kar", "audio/midi"},
+
97  {"midi", "audio/midi"},
+
98  {"mid", "audio/midi"},
+
99  {"mp3", "audio/mpeg"},
+
100  {"ogg", "audio/ogg"},
+
101  {"m4a", "audio/x-m4a"},
+
102  {"ra", "audio/x-realaudio"},
+
103  {"3gp", "video/3gpp"},
+
104  {"3gpp", "video/3gpp"},
+
105  {"ts", "video/mp2t"},
+
106  {"mp4", "video/mp4"},
+
107  {"mpg", "video/mpeg"},
+
108  {"mpeg", "video/mpeg"},
+
109  {"mov", "video/quicktime"},
+
110  {"webm", "video/webm"},
+
111  {"flv", "video/x-flv"},
+
112  {"m4v", "video/x-m4v"},
+
113  {"mng", "video/x-mng"},
+
114  {"asf", "video/x-ms-asf"},
+
115  {"asx", "video/x-ms-asf"},
+
116  {"wmv", "video/x-ms-wmv"},
+
117  {"avi", "video/x-msvideo"}};
+
118 }
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/multipart_8h_source.html b/1.2/reference/multipart_8h_source.html new file mode 100644 index 000000000..b1d7f7191 --- /dev/null +++ b/1.2/reference/multipart_8h_source.html @@ -0,0 +1,413 @@ + + + + + + + + Crow: include/crow/multipart.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
multipart.h
+
+
+
1 #pragma once
+
2 
+
3 #include <string>
+
4 #include <vector>
+
5 #include <sstream>
+
6 
+
7 #include "crow/http_request.h"
+
8 #include "crow/returnable.h"
+
9 #include "crow/ci_map.h"
+
10 
+
11 namespace crow
+
12 {
+
13 
+
14  /// Encapsulates anything related to processing and organizing `multipart/xyz` messages
+
15  namespace multipart
+
16  {
+
17 
+
18  const std::string dd = "--";
+
19 
+
20  /// The first part in a section, contains metadata about the part
+
21  struct header
+
22  {
+
23  std::string value; ///< The first part of the header, usually `Content-Type` or `Content-Disposition`
+
24  std::unordered_map<std::string, std::string> params; ///< The parameters of the header, come after the `value`
+
25 
+
26  operator int() const { return std::stoi(value); } ///< Returns \ref value as integer
+
27  operator double() const { return std::stod(value); } ///< Returns \ref value as double
+
28  };
+
29 
+
30  /// Multipart header map (key is header key).
+
31  using mph_map = std::unordered_multimap<std::string, header, ci_hash, ci_key_eq>;
+
32 
+
33  /// Find and return the value object associated with the key. (returns an empty class if nothing is found)
+
34  template<typename O, typename T>
+
35  inline const O& get_header_value_object(const T& headers, const std::string& key)
+
36  {
+
37  if (headers.count(key))
+
38  {
+
39  return headers.find(key)->second;
+
40  }
+
41  static O empty;
+
42  return empty;
+
43  }
+
44 
+
45  /// Same as \ref get_header_value_object() but for \ref multipart.header
+
46  template<typename T>
+
47  inline const header& get_header_object(const T& headers, const std::string& key)
+
48  {
+
49  return get_header_value_object<header>(headers, key);
+
50  }
+
51 
+
52  ///One part of the multipart message
+
53 
+
54  ///
+
55  /// It is usually separated from other sections by a `boundary`
+
56  struct part
+
57  {
+
58  mph_map headers; ///< (optional) The first part before the data, Contains information regarding the type of data and encoding
+
59  std::string body; ///< The actual data in the part
+
60 
+
61  operator int() const { return std::stoi(body); } ///< Returns \ref body as integer
+
62  operator double() const { return std::stod(body); } ///< Returns \ref body as double
+
63 
+
64  const header& get_header_object(const std::string& key) const
+
65  {
+ +
67  }
+
68  };
+
69 
+
70  /// Multipart map (key is the name parameter).
+
71  using mp_map = std::unordered_multimap<std::string, part, ci_hash, ci_key_eq>;
+
72 
+
73  /// The parsed multipart request/response
+
74  struct message : public returnable
+
75  {
+
76  ci_map headers; ///< The request/response headers
+
77  std::string boundary; ///< The text boundary that separates different `parts`
+
78  std::vector<part> parts; ///< The individual parts of the message
+
79  mp_map part_map; ///< The individual parts of the message, organized in a map with the `name` header parameter being the key
+
80 
+
81  const std::string& get_header_value(const std::string& key) const
+
82  {
+
83  return crow::get_header_value(headers, key);
+
84  }
+
85 
+
86  part get_part_by_name(const std::string& name)
+
87  {
+
88  mp_map::iterator result = part_map.find(name);
+
89  if (result != part_map.end())
+
90  return result->second;
+
91  else
+
92  return {};
+
93  }
+
94 
+
95  /// Represent all parts as a string (**does not include message headers**)
+
96  std::string dump() const override
+
97  {
+
98  std::stringstream str;
+
99  std::string delimiter = dd + boundary;
+
100 
+
101  for (unsigned i = 0; i < parts.size(); i++)
+
102  {
+
103  str << delimiter << crlf;
+
104  str << dump(i);
+
105  }
+
106  str << delimiter << dd << crlf;
+
107  return str.str();
+
108  }
+
109 
+
110  /// Represent an individual part as a string
+
111  std::string dump(int part_) const
+
112  {
+
113  std::stringstream str;
+
114  part item = parts[part_];
+
115  for (auto& item_h : item.headers)
+
116  {
+
117  str << item_h.first << ": " << item_h.second.value;
+
118  for (auto& it : item_h.second.params)
+
119  {
+
120  str << "; " << it.first << '=' << pad(it.second);
+
121  }
+
122  str << crlf;
+
123  }
+
124  str << crlf;
+
125  str << item.body << crlf;
+
126  return str.str();
+
127  }
+
128 
+
129  /// Default constructor using default values
+
130  message(const ci_map& headers, const std::string& boundary, const std::vector<part>& sections):
+
131  returnable("multipart/form-data; boundary=CROW-BOUNDARY"), headers(headers), boundary(boundary), parts(sections)
+
132  {
+
133  if (!boundary.empty())
+
134  content_type = "multipart/form-data; boundary=" + boundary;
+
135  for (auto& item : parts)
+
136  {
+
137  part_map.emplace(
+
138  (get_header_object(item.headers, "Content-Disposition").params.find("name")->second),
+
139  item);
+
140  }
+
141  }
+
142 
+
143  /// Create a multipart message from a request data
+
144  message(const request& req):
+
145  returnable("multipart/form-data; boundary=CROW-BOUNDARY"),
+
146  headers(req.headers),
+
147  boundary(get_boundary(get_header_value("Content-Type")))
+
148  {
+
149  if (!boundary.empty())
+
150  content_type = "multipart/form-data; boundary=" + boundary;
+
151  parse_body(req.body, parts, part_map);
+
152  }
+
153 
+
154  private:
+
155  std::string get_boundary(const std::string& header) const
+
156  {
+
157  constexpr char boundary_text[] = "boundary=";
+
158  size_t found = header.find(boundary_text);
+
159  if (found != std::string::npos)
+
160  {
+
161  std::string to_return(header.substr(found + strlen(boundary_text)));
+
162  if (to_return[0] == '\"')
+
163  {
+
164  to_return = to_return.substr(1, to_return.length() - 2);
+
165  }
+
166  return to_return;
+
167  }
+
168  return std::string();
+
169  }
+
170 
+
171  void parse_body(std::string body, std::vector<part>& sections, mp_map& part_map)
+
172  {
+
173 
+
174  std::string delimiter = dd + boundary;
+
175 
+
176  // TODO(EDev): Exit on error
+
177  while (body != (crlf))
+
178  {
+
179  size_t found = body.find(delimiter);
+
180  if (found == std::string::npos)
+
181  {
+
182  // did not find delimiter; probably an ill-formed body; ignore the rest
+
183  break;
+
184  }
+
185  std::string section = body.substr(0, found);
+
186 
+
187  // +2 is the CRLF.
+
188  // We don't check it and delete it so that the same delimiter can be used for The last delimiter (--delimiter--CRLF).
+
189  body.erase(0, found + delimiter.length() + 2);
+
190  if (!section.empty())
+
191  {
+
192  part parsed_section(parse_section(section));
+
193  part_map.emplace(
+
194  (get_header_object(parsed_section.headers, "Content-Disposition").params.find("name")->second),
+
195  parsed_section);
+
196  sections.push_back(std::move(parsed_section));
+
197  }
+
198  }
+
199  }
+
200 
+
201  part parse_section(std::string& section)
+
202  {
+
203  struct part to_return;
+
204 
+
205  size_t found = section.find(crlf + crlf);
+
206  std::string head_line = section.substr(0, found + 2);
+
207  section.erase(0, found + 4);
+
208 
+
209  parse_section_head(head_line, to_return);
+
210  to_return.body = section.substr(0, section.length() - 2);
+
211  return to_return;
+
212  }
+
213 
+
214  void parse_section_head(std::string& lines, part& part)
+
215  {
+
216  while (!lines.empty())
+
217  {
+
218  header to_add;
+
219 
+
220  size_t found = lines.find(crlf);
+
221  std::string line = lines.substr(0, found);
+
222  std::string key;
+
223  lines.erase(0, found + 2);
+
224  // Add the header if available
+
225  if (!line.empty())
+
226  {
+
227  size_t found = line.find("; ");
+
228  std::string header = line.substr(0, found);
+
229  if (found != std::string::npos)
+
230  line.erase(0, found + 2);
+
231  else
+
232  line = std::string();
+
233 
+
234  size_t header_split = header.find(": ");
+
235  key = header.substr(0, header_split);
+
236 
+
237  to_add.value = header.substr(header_split + 2);
+
238  }
+
239 
+
240  // Add the parameters
+
241  while (!line.empty())
+
242  {
+
243  size_t found = line.find("; ");
+
244  std::string param = line.substr(0, found);
+
245  if (found != std::string::npos)
+
246  line.erase(0, found + 2);
+
247  else
+
248  line = std::string();
+
249 
+
250  size_t param_split = param.find('=');
+
251 
+
252  std::string value = param.substr(param_split + 1);
+
253 
+
254  to_add.params.emplace(param.substr(0, param_split), trim(value));
+
255  }
+
256  part.headers.emplace(key, to_add);
+
257  }
+
258  }
+
259 
+
260  inline std::string trim(std::string& string, const char& excess = '"') const
+
261  {
+
262  if (string.length() > 1 && string[0] == excess && string[string.length() - 1] == excess)
+
263  return string.substr(1, string.length() - 2);
+
264  return string;
+
265  }
+
266 
+
267  inline std::string pad(std::string& string, const char& padding = '"') const
+
268  {
+
269  return (padding + string + padding);
+
270  }
+
271  };
+
272  } // namespace multipart
+
273 } // namespace crow
+
std::unordered_multimap< std::string, part, ci_hash, ci_key_eq > mp_map
Multipart map (key is the name parameter).
Definition: multipart.h:71
+
std::unordered_multimap< std::string, header, ci_hash, ci_key_eq > mph_map
Multipart header map (key is header key).
Definition: multipart.h:31
+
const header & get_header_object(const T &headers, const std::string &key)
Same as get_header_value_object() but for multipart::header.
Definition: multipart.h:47
+
const O & get_header_value_object(const T &headers, const std::string &key)
Find and return the value object associated with the key. (returns an empty class if nothing is found...
Definition: multipart.h:35
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
const std::string & get_header_value(const T &headers, const std::string &key)
Find and return the value associated with the key. (returns an empty string if nothing is found)
Definition: http_request.h:24
+
The first part in a section, contains metadata about the part.
Definition: multipart.h:22
+
std::unordered_map< std::string, std::string > params
The parameters of the header, come after the value
Definition: multipart.h:24
+
std::string value
The first part of the header, usually Content-Type or Content-Disposition
Definition: multipart.h:23
+
The parsed multipart request/response.
Definition: multipart.h:75
+
message(const ci_map &headers, const std::string &boundary, const std::vector< part > &sections)
Default constructor using default values.
Definition: multipart.h:130
+
std::vector< part > parts
The individual parts of the message.
Definition: multipart.h:78
+
message(const request &req)
Create a multipart message from a request data.
Definition: multipart.h:144
+
std::string boundary
The text boundary that separates different parts
Definition: multipart.h:77
+
mp_map part_map
The individual parts of the message, organized in a map with the name header parameter being the key.
Definition: multipart.h:79
+
std::string dump(int part_) const
Represent an individual part as a string.
Definition: multipart.h:111
+
std::string dump() const override
Represent all parts as a string (does not include message headers)
Definition: multipart.h:96
+
ci_map headers
The request/response headers.
Definition: multipart.h:76
+
One part of the multipart message.
Definition: multipart.h:57
+
mph_map headers
(optional) The first part before the data, Contains information regarding the type of data and encodi...
Definition: multipart.h:58
+
std::string body
The actual data in the part.
Definition: multipart.h:59
+
An HTTP request.
Definition: http_request.h:36
+
An abstract class that allows any other class to be returned by a handler.
Definition: returnable.h:9
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/mustache_8h_source.html b/1.2/reference/mustache_8h_source.html new file mode 100644 index 000000000..3b1440db8 --- /dev/null +++ b/1.2/reference/mustache_8h_source.html @@ -0,0 +1,850 @@ + + + + + + + + Crow: include/crow/mustache.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
mustache.h
+
+
+
1 #pragma once
+
2 #include <string>
+
3 #include <vector>
+
4 #include <fstream>
+
5 #include <iterator>
+
6 #include <functional>
+
7 #include "crow/json.h"
+
8 #include "crow/logging.h"
+
9 #include "crow/returnable.h"
+
10 #include "crow/utility.h"
+
11 
+
12 namespace crow
+
13 {
+
14  namespace mustache
+
15  {
+
16  using context = json::wvalue;
+
17 
+
18  template_t load(const std::string& filename);
+
19 
+
20  class invalid_template_exception : public std::exception
+
21  {
+
22  public:
+
23  invalid_template_exception(const std::string& msg):
+
24  msg("crow::mustache error: " + msg)
+
25  {}
+
26  virtual const char* what() const throw()
+
27  {
+
28  return msg.c_str();
+
29  }
+
30  std::string msg;
+
31  };
+
32 
+ +
34  {
+ +
36  returnable("text/html") {}
+
37 
+
38  rendered_template(std::string& body):
+
39  returnable("text/html"), body_(std::move(body)) {}
+
40 
+
41  std::string body_;
+
42 
+
43  std::string dump() const override
+
44  {
+
45  return body_;
+
46  }
+
47  };
+
48 
+
49  enum class ActionType
+
50  {
+
51  Ignore,
+
52  Tag,
+
53  UnescapeTag,
+
54  OpenBlock,
+
55  CloseBlock,
+
56  ElseBlock,
+
57  Partial,
+
58  };
+
59 
+
60  struct Action
+
61  {
+
62  int start;
+
63  int end;
+
64  int pos;
+
65  ActionType t;
+
66  Action(ActionType t, size_t start, size_t end, size_t pos = 0):
+
67  start(static_cast<int>(start)), end(static_cast<int>(end)), pos(static_cast<int>(pos)), t(t)
+
68  {
+
69  }
+
70  };
+
71 
+
72  /// A mustache template object.
+
73  class template_t
+
74  {
+
75  public:
+
76  template_t(std::string body):
+
77  body_(std::move(body))
+
78  {
+
79  // {{ {{# {{/ {{^ {{! {{> {{=
+
80  parse();
+
81  }
+
82 
+
83  private:
+
84  std::string tag_name(const Action& action) const
+
85  {
+
86  return body_.substr(action.start, action.end - action.start);
+
87  }
+
88  auto find_context(const std::string& name, const std::vector<const context*>& stack, bool shouldUseOnlyFirstStackValue = false) const -> std::pair<bool, const context&>
+
89  {
+
90  if (name == ".")
+
91  {
+
92  return {true, *stack.back()};
+
93  }
+
94  static json::wvalue empty_str;
+
95  empty_str = "";
+
96 
+
97  int dotPosition = name.find(".");
+
98  if (dotPosition == static_cast<int>(name.npos))
+
99  {
+
100  for (auto it = stack.rbegin(); it != stack.rend(); ++it)
+
101  {
+
102  if ((*it)->t() == json::type::Object)
+
103  {
+
104  if ((*it)->count(name))
+
105  return {true, (**it)[name]};
+
106  }
+
107  }
+
108  }
+
109  else
+
110  {
+
111  std::vector<int> dotPositions;
+
112  dotPositions.push_back(-1);
+
113  while (dotPosition != static_cast<int>(name.npos))
+
114  {
+
115  dotPositions.push_back(dotPosition);
+
116  dotPosition = name.find(".", dotPosition + 1);
+
117  }
+
118  dotPositions.push_back(name.size());
+
119  std::vector<std::string> names;
+
120  names.reserve(dotPositions.size() - 1);
+
121  for (int i = 1; i < static_cast<int>(dotPositions.size()); i++)
+
122  names.emplace_back(name.substr(dotPositions[i - 1] + 1, dotPositions[i] - dotPositions[i - 1] - 1));
+
123 
+
124  for (auto it = stack.rbegin(); it != stack.rend(); ++it)
+
125  {
+
126  const context* view = *it;
+
127  bool found = true;
+
128  for (auto jt = names.begin(); jt != names.end(); ++jt)
+
129  {
+
130  if (view->t() == json::type::Object &&
+
131  view->count(*jt))
+
132  {
+
133  view = &(*view)[*jt];
+
134  }
+
135  else
+
136  {
+
137  if (shouldUseOnlyFirstStackValue)
+
138  {
+
139  return {false, empty_str};
+
140  }
+
141  found = false;
+
142  break;
+
143  }
+
144  }
+
145  if (found)
+
146  return {true, *view};
+
147  }
+
148  }
+
149 
+
150  return {false, empty_str};
+
151  }
+
152 
+
153  void escape(const std::string& in, std::string& out) const
+
154  {
+
155  out.reserve(out.size() + in.size());
+
156  for (auto it = in.begin(); it != in.end(); ++it)
+
157  {
+
158  switch (*it)
+
159  {
+
160  case '&': out += "&amp;"; break;
+
161  case '<': out += "&lt;"; break;
+
162  case '>': out += "&gt;"; break;
+
163  case '"': out += "&quot;"; break;
+
164  case '\'': out += "&#39;"; break;
+
165  case '/': out += "&#x2F;"; break;
+
166  case '`': out += "&#x60;"; break;
+
167  case '=': out += "&#x3D;"; break;
+
168  default: out += *it; break;
+
169  }
+
170  }
+
171  }
+
172 
+
173  bool isTagInsideObjectBlock(const int& current, const std::vector<const context*>& stack) const
+
174  {
+
175  int openedBlock = 0;
+
176  for (int i = current; i > 0; --i)
+
177  {
+
178  auto& action = actions_[i - 1];
+
179 
+
180  if (action.t == ActionType::OpenBlock)
+
181  {
+
182  if (openedBlock == 0 && (*stack.rbegin())->t() == json::type::Object)
+
183  {
+
184  return true;
+
185  }
+
186  --openedBlock;
+
187  }
+
188  else if (action.t == ActionType::CloseBlock)
+
189  {
+
190  ++openedBlock;
+
191  }
+
192  }
+
193 
+
194  return false;
+
195  }
+
196 
+
197  void render_internal(int actionBegin, int actionEnd, std::vector<const context*>& stack, std::string& out, int indent) const
+
198  {
+
199  int current = actionBegin;
+
200 
+
201  if (indent)
+
202  out.insert(out.size(), indent, ' ');
+
203 
+
204  while (current < actionEnd)
+
205  {
+
206  auto& fragment = fragments_[current];
+
207  auto& action = actions_[current];
+
208  render_fragment(fragment, indent, out);
+
209  switch (action.t)
+
210  {
+
211  case ActionType::Ignore:
+
212  // do nothing
+
213  break;
+
214  case ActionType::Partial:
+
215  {
+
216  std::string partial_name = tag_name(action);
+
217  auto partial_templ = load(partial_name);
+
218  int partial_indent = action.pos;
+
219  partial_templ.render_internal(0, partial_templ.fragments_.size() - 1, stack, out, partial_indent ? indent + partial_indent : 0);
+
220  }
+
221  break;
+
222  case ActionType::UnescapeTag:
+
223  case ActionType::Tag:
+
224  {
+
225  bool shouldUseOnlyFirstStackValue = false;
+
226  if (isTagInsideObjectBlock(current, stack))
+
227  {
+
228  shouldUseOnlyFirstStackValue = true;
+
229  }
+
230  auto optional_ctx = find_context(tag_name(action), stack, shouldUseOnlyFirstStackValue);
+
231  auto& ctx = optional_ctx.second;
+
232  switch (ctx.t())
+
233  {
+
234  case json::type::False:
+
235  case json::type::True:
+
236  case json::type::Number:
+
237  out += ctx.dump();
+
238  break;
+
239  case json::type::String:
+
240  if (action.t == ActionType::Tag)
+
241  escape(ctx.s, out);
+
242  else
+
243  out += ctx.s;
+
244  break;
+
245  case json::type::Function:
+
246  {
+
247  std::string execute_result = ctx.execute();
+
248  while (execute_result.find("{{") != std::string::npos)
+
249  {
+
250  template_t result_plug(execute_result);
+
251  execute_result = result_plug.render_string(*(stack[0]));
+
252  }
+
253 
+
254  if (action.t == ActionType::Tag)
+
255  escape(execute_result, out);
+
256  else
+
257  out += execute_result;
+
258  }
+
259  break;
+
260  default:
+
261  throw std::runtime_error("not implemented tag type" + utility::lexical_cast<std::string>(static_cast<int>(ctx.t())));
+
262  }
+
263  }
+
264  break;
+
265  case ActionType::ElseBlock:
+
266  {
+
267  static context nullContext;
+
268  auto optional_ctx = find_context(tag_name(action), stack);
+
269  if (!optional_ctx.first)
+
270  {
+
271  stack.emplace_back(&nullContext);
+
272  break;
+
273  }
+
274 
+
275  auto& ctx = optional_ctx.second;
+
276  switch (ctx.t())
+
277  {
+
278  case json::type::List:
+
279  if (ctx.l && !ctx.l->empty())
+
280  current = action.pos;
+
281  else
+
282  stack.emplace_back(&nullContext);
+
283  break;
+
284  case json::type::False:
+
285  case json::type::Null:
+
286  stack.emplace_back(&nullContext);
+
287  break;
+
288  default:
+
289  current = action.pos;
+
290  break;
+
291  }
+
292  break;
+
293  }
+
294  case ActionType::OpenBlock:
+
295  {
+
296  auto optional_ctx = find_context(tag_name(action), stack);
+
297  if (!optional_ctx.first)
+
298  {
+
299  current = action.pos;
+
300  break;
+
301  }
+
302 
+
303  auto& ctx = optional_ctx.second;
+
304  switch (ctx.t())
+
305  {
+
306  case json::type::List:
+
307  if (ctx.l)
+
308  for (auto it = ctx.l->begin(); it != ctx.l->end(); ++it)
+
309  {
+
310  stack.push_back(&*it);
+
311  render_internal(current + 1, action.pos, stack, out, indent);
+
312  stack.pop_back();
+
313  }
+
314  current = action.pos;
+
315  break;
+
316  case json::type::Number:
+
317  case json::type::String:
+
318  case json::type::Object:
+
319  case json::type::True:
+
320  stack.push_back(&ctx);
+
321  break;
+
322  case json::type::False:
+
323  case json::type::Null:
+
324  current = action.pos;
+
325  break;
+
326  default:
+
327  throw std::runtime_error("{{#: not implemented context type: " + utility::lexical_cast<std::string>(static_cast<int>(ctx.t())));
+
328  break;
+
329  }
+
330  break;
+
331  }
+
332  case ActionType::CloseBlock:
+
333  stack.pop_back();
+
334  break;
+
335  default:
+
336  throw std::runtime_error("not implemented " + utility::lexical_cast<std::string>(static_cast<int>(action.t)));
+
337  }
+
338  current++;
+
339  }
+
340  auto& fragment = fragments_[actionEnd];
+
341  render_fragment(fragment, indent, out);
+
342  }
+
343  void render_fragment(const std::pair<int, int> fragment, int indent, std::string& out) const
+
344  {
+
345  if (indent)
+
346  {
+
347  for (int i = fragment.first; i < fragment.second; i++)
+
348  {
+
349  out += body_[i];
+
350  if (body_[i] == '\n' && i + 1 != static_cast<int>(body_.size()))
+
351  out.insert(out.size(), indent, ' ');
+
352  }
+
353  }
+
354  else
+
355  out.insert(out.size(), body_, fragment.first, fragment.second - fragment.first);
+
356  }
+
357 
+
358  public:
+
359  /// Output a returnable template from this mustache template
+ +
361  {
+
362  context empty_ctx;
+
363  std::vector<const context*> stack;
+
364  stack.emplace_back(&empty_ctx);
+
365 
+
366  std::string ret;
+
367  render_internal(0, fragments_.size() - 1, stack, ret, 0);
+
368  return rendered_template(ret);
+
369  }
+
370 
+
371  /// Apply the values from the context provided and output a returnable template from this mustache template
+
372  rendered_template render(const context& ctx) const
+
373  {
+
374  std::vector<const context*> stack;
+
375  stack.emplace_back(&ctx);
+
376 
+
377  std::string ret;
+
378  render_internal(0, fragments_.size() - 1, stack, ret, 0);
+
379  return rendered_template(ret);
+
380  }
+
381 
+
382  /// Apply the values from the context provided and output a returnable template from this mustache template
+
383  rendered_template render(const context&& ctx) const
+
384  {
+
385  return render(ctx);
+
386  }
+
387 
+
388  /// Output a returnable template from this mustache template
+
389  std::string render_string() const
+
390  {
+
391  context empty_ctx;
+
392  std::vector<const context*> stack;
+
393  stack.emplace_back(&empty_ctx);
+
394 
+
395  std::string ret;
+
396  render_internal(0, fragments_.size() - 1, stack, ret, 0);
+
397  return ret;
+
398  }
+
399 
+
400  /// Apply the values from the context provided and output a returnable template from this mustache template
+
401  std::string render_string(const context& ctx) const
+
402  {
+
403  std::vector<const context*> stack;
+
404  stack.emplace_back(&ctx);
+
405 
+
406  std::string ret;
+
407  render_internal(0, fragments_.size() - 1, stack, ret, 0);
+
408  return ret;
+
409  }
+
410 
+
411  private:
+
412  void parse()
+
413  {
+
414  std::string tag_open = "{{";
+
415  std::string tag_close = "}}";
+
416 
+
417  std::vector<int> blockPositions;
+
418 
+
419  size_t current = 0;
+
420  while (1)
+
421  {
+
422  size_t idx = body_.find(tag_open, current);
+
423  if (idx == body_.npos)
+
424  {
+
425  fragments_.emplace_back(static_cast<int>(current), static_cast<int>(body_.size()));
+
426  actions_.emplace_back(ActionType::Ignore, 0, 0);
+
427  break;
+
428  }
+
429  fragments_.emplace_back(static_cast<int>(current), static_cast<int>(idx));
+
430 
+
431  idx += tag_open.size();
+
432  size_t endIdx = body_.find(tag_close, idx);
+
433  if (endIdx == idx)
+
434  {
+
435  throw invalid_template_exception("empty tag is not allowed");
+
436  }
+
437  if (endIdx == body_.npos)
+
438  {
+
439  // error, no matching tag
+
440  throw invalid_template_exception("not matched opening tag");
+
441  }
+
442  current = endIdx + tag_close.size();
+
443  switch (body_[idx])
+
444  {
+
445  case '#':
+
446  idx++;
+
447  while (body_[idx] == ' ')
+
448  idx++;
+
449  while (body_[endIdx - 1] == ' ')
+
450  endIdx--;
+
451  blockPositions.emplace_back(static_cast<int>(actions_.size()));
+
452  actions_.emplace_back(ActionType::OpenBlock, idx, endIdx);
+
453  break;
+
454  case '/':
+
455  idx++;
+
456  while (body_[idx] == ' ')
+
457  idx++;
+
458  while (body_[endIdx - 1] == ' ')
+
459  endIdx--;
+
460  {
+
461  auto& matched = actions_[blockPositions.back()];
+
462  if (body_.compare(idx, endIdx - idx,
+
463  body_, matched.start, matched.end - matched.start) != 0)
+
464  {
+
465  throw invalid_template_exception("not matched {{# {{/ pair: " +
+
466  body_.substr(matched.start, matched.end - matched.start) + ", " +
+
467  body_.substr(idx, endIdx - idx));
+
468  }
+
469  matched.pos = actions_.size();
+
470  }
+
471  actions_.emplace_back(ActionType::CloseBlock, idx, endIdx, blockPositions.back());
+
472  blockPositions.pop_back();
+
473  break;
+
474  case '^':
+
475  idx++;
+
476  while (body_[idx] == ' ')
+
477  idx++;
+
478  while (body_[endIdx - 1] == ' ')
+
479  endIdx--;
+
480  blockPositions.emplace_back(static_cast<int>(actions_.size()));
+
481  actions_.emplace_back(ActionType::ElseBlock, idx, endIdx);
+
482  break;
+
483  case '!':
+
484  // do nothing action
+
485  actions_.emplace_back(ActionType::Ignore, idx + 1, endIdx);
+
486  break;
+
487  case '>': // partial
+
488  idx++;
+
489  while (body_[idx] == ' ')
+
490  idx++;
+
491  while (body_[endIdx - 1] == ' ')
+
492  endIdx--;
+
493  actions_.emplace_back(ActionType::Partial, idx, endIdx);
+
494  break;
+
495  case '{':
+
496  if (tag_open != "{{" || tag_close != "}}")
+
497  throw invalid_template_exception("cannot use triple mustache when delimiter changed");
+
498 
+
499  idx++;
+
500  if (body_[endIdx + 2] != '}')
+
501  {
+
502  throw invalid_template_exception("{{{: }}} not matched");
+
503  }
+
504  while (body_[idx] == ' ')
+
505  idx++;
+
506  while (body_[endIdx - 1] == ' ')
+
507  endIdx--;
+
508  actions_.emplace_back(ActionType::UnescapeTag, idx, endIdx);
+
509  current++;
+
510  break;
+
511  case '&':
+
512  idx++;
+
513  while (body_[idx] == ' ')
+
514  idx++;
+
515  while (body_[endIdx - 1] == ' ')
+
516  endIdx--;
+
517  actions_.emplace_back(ActionType::UnescapeTag, idx, endIdx);
+
518  break;
+
519  case '=':
+
520  // tag itself is no-op
+
521  idx++;
+
522  actions_.emplace_back(ActionType::Ignore, idx, endIdx);
+
523  endIdx--;
+
524  if (body_[endIdx] != '=')
+
525  throw invalid_template_exception("{{=: not matching = tag: " + body_.substr(idx, endIdx - idx));
+
526  endIdx--;
+
527  while (body_[idx] == ' ')
+
528  idx++;
+
529  while (body_[endIdx] == ' ')
+
530  endIdx--;
+
531  endIdx++;
+
532  {
+
533  bool succeeded = false;
+
534  for (size_t i = idx; i < endIdx; i++)
+
535  {
+
536  if (body_[i] == ' ')
+
537  {
+
538  tag_open = body_.substr(idx, i - idx);
+
539  while (body_[i] == ' ')
+
540  i++;
+
541  tag_close = body_.substr(i, endIdx - i);
+
542  if (tag_open.empty())
+
543  throw invalid_template_exception("{{=: empty open tag");
+
544  if (tag_close.empty())
+
545  throw invalid_template_exception("{{=: empty close tag");
+
546 
+
547  if (tag_close.find(" ") != tag_close.npos)
+
548  throw invalid_template_exception("{{=: invalid open/close tag: " + tag_open + " " + tag_close);
+
549  succeeded = true;
+
550  break;
+
551  }
+
552  }
+
553  if (!succeeded)
+
554  throw invalid_template_exception("{{=: cannot find space between new open/close tags");
+
555  }
+
556  break;
+
557  default:
+
558  // normal tag case;
+
559  while (body_[idx] == ' ')
+
560  idx++;
+
561  while (body_[endIdx - 1] == ' ')
+
562  endIdx--;
+
563  actions_.emplace_back(ActionType::Tag, idx, endIdx);
+
564  break;
+
565  }
+
566  }
+
567 
+
568  // removing standalones
+
569  for (int i = actions_.size() - 2; i >= 0; i--)
+
570  {
+
571  if (actions_[i].t == ActionType::Tag || actions_[i].t == ActionType::UnescapeTag)
+
572  continue;
+
573  auto& fragment_before = fragments_[i];
+
574  auto& fragment_after = fragments_[i + 1];
+
575  bool is_last_action = i == static_cast<int>(actions_.size()) - 2;
+
576  bool all_space_before = true;
+
577  int j, k;
+
578  for (j = fragment_before.second - 1; j >= fragment_before.first; j--)
+
579  {
+
580  if (body_[j] != ' ')
+
581  {
+
582  all_space_before = false;
+
583  break;
+
584  }
+
585  }
+
586  if (all_space_before && i > 0)
+
587  continue;
+
588  if (!all_space_before && body_[j] != '\n')
+
589  continue;
+
590  bool all_space_after = true;
+
591  for (k = fragment_after.first; k < static_cast<int>(body_.size()) && k < fragment_after.second; k++)
+
592  {
+
593  if (body_[k] != ' ')
+
594  {
+
595  all_space_after = false;
+
596  break;
+
597  }
+
598  }
+
599  if (all_space_after && !is_last_action)
+
600  continue;
+
601  if (!all_space_after &&
+
602  !(
+
603  body_[k] == '\n' ||
+
604  (body_[k] == '\r' &&
+
605  k + 1 < static_cast<int>(body_.size()) &&
+
606  body_[k + 1] == '\n')))
+
607  continue;
+
608  if (actions_[i].t == ActionType::Partial)
+
609  {
+
610  actions_[i].pos = fragment_before.second - j - 1;
+
611  }
+
612  fragment_before.second = j + 1;
+
613  if (!all_space_after)
+
614  {
+
615  if (body_[k] == '\n')
+
616  k++;
+
617  else
+
618  k += 2;
+
619  fragment_after.first = k;
+
620  }
+
621  }
+
622  }
+
623 
+
624  std::vector<std::pair<int, int>> fragments_;
+
625  std::vector<Action> actions_;
+
626  std::string body_;
+
627  };
+
628 
+
629  inline template_t compile(const std::string& body)
+
630  {
+
631  return template_t(body);
+
632  }
+
633  namespace detail
+
634  {
+
635  inline std::string& get_template_base_directory_ref()
+
636  {
+
637  static std::string template_base_directory = "templates";
+
638  return template_base_directory;
+
639  }
+
640 
+
641  /// A base directory not related to any blueprint
+
642  inline std::string& get_global_template_base_directory_ref()
+
643  {
+
644  static std::string template_base_directory = "templates";
+
645  return template_base_directory;
+
646  }
+
647  } // namespace detail
+
648 
+
649  inline std::string default_loader(const std::string& filename)
+
650  {
+
651  std::string path = detail::get_template_base_directory_ref();
+
652  std::ifstream inf(utility::join_path(path, filename));
+
653  if (!inf)
+
654  {
+
655  CROW_LOG_WARNING << "Template \"" << filename << "\" not found.";
+
656  return {};
+
657  }
+
658  return {std::istreambuf_iterator<char>(inf), std::istreambuf_iterator<char>()};
+
659  }
+
660 
+
661  namespace detail
+
662  {
+
663  inline std::function<std::string(std::string)>& get_loader_ref()
+
664  {
+
665  static std::function<std::string(std::string)> loader = default_loader;
+
666  return loader;
+
667  }
+
668  } // namespace detail
+
669 
+
670  inline void set_base(const std::string& path)
+
671  {
+
672  auto& base = detail::get_template_base_directory_ref();
+
673  base = path;
+
674  if (base.back() != '\\' &&
+
675  base.back() != '/')
+
676  {
+
677  base += '/';
+
678  }
+
679  }
+
680 
+
681  inline void set_global_base(const std::string& path)
+
682  {
+
683  auto& base = detail::get_global_template_base_directory_ref();
+
684  base = path;
+
685  if (base.back() != '\\' &&
+
686  base.back() != '/')
+
687  {
+
688  base += '/';
+
689  }
+
690  }
+
691 
+
692  inline void set_loader(std::function<std::string(std::string)> loader)
+
693  {
+
694  detail::get_loader_ref() = std::move(loader);
+
695  }
+
696 
+
697  inline std::string load_text(const std::string& filename)
+
698  {
+
699  std::string filename_sanitized(filename);
+
700  utility::sanitize_filename(filename_sanitized);
+
701  return detail::get_loader_ref()(filename_sanitized);
+
702  }
+
703 
+
704  inline std::string load_text_unsafe(const std::string& filename)
+
705  {
+
706  return detail::get_loader_ref()(filename);
+
707  }
+
708 
+
709  inline template_t load(const std::string& filename)
+
710  {
+
711  std::string filename_sanitized(filename);
+
712  utility::sanitize_filename(filename_sanitized);
+
713  return compile(detail::get_loader_ref()(filename_sanitized));
+
714  }
+
715 
+
716  inline template_t load_unsafe(const std::string& filename)
+
717  {
+
718  return compile(detail::get_loader_ref()(filename));
+
719  }
+
720  } // namespace mustache
+
721 } // namespace crow
+
JSON write value.
Definition: json.h:1289
+ +
A mustache template object.
Definition: mustache.h:74
+
std::string render_string() const
Output a returnable template from this mustache template.
Definition: mustache.h:389
+
rendered_template render() const
Output a returnable template from this mustache template.
Definition: mustache.h:360
+
rendered_template render(const context &ctx) const
Apply the values from the context provided and output a returnable template from this mustache templa...
Definition: mustache.h:372
+
rendered_template render(const context &&ctx) const
Apply the values from the context provided and output a returnable template from this mustache templa...
Definition: mustache.h:383
+
std::string render_string(const context &ctx) const
Apply the values from the context provided and output a returnable template from this mustache templa...
Definition: mustache.h:401
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
Definition: mustache.h:61
+
Definition: mustache.h:34
+
An abstract class that allows any other class to be returned by a handler.
Definition: returnable.h:9
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/namespacecrow.html b/1.2/reference/namespacecrow.html new file mode 100644 index 000000000..04485d94d --- /dev/null +++ b/1.2/reference/namespacecrow.html @@ -0,0 +1,644 @@ + + + + + + + + Crow: crow Namespace Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow Namespace Reference
+
+
+ +

The main namespace of the library. In this namespace is defined the most important classes and functions of the library. +More...

+ + + + + + + + +

+Namespaces

 multipart
 Encapsulates anything related to processing and organizing multipart/xyz messages.
 
 websocket
 Namespace that includes the Connection class and connection struct. Useful for WebSockets connection.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Classes

class  Crow
 The main server application class. More...
 
struct  ci_hash
 Hashing function for ci_map (unordered_multimap). More...
 
struct  ci_key_eq
 Equals function for ci_map (unordered_multimap). More...
 
struct  routing_handle_result
 
class  Connection
 An HTTP connection. More...
 
struct  http_parser
 
struct  http_parser_settings
 
struct  request
 An HTTP request. More...
 
struct  response
 HTTP response. More...
 
class  Server
 
class  ILogHandler
 
class  CerrLogHandler
 
class  logger
 
struct  ILocalMiddleware
 Local middleware should extend ILocalMiddleware. More...
 
struct  CookieParser
 
struct  CORSRules
 Used for tuning CORS policies. More...
 
struct  CORSHandler
 CORSHandler is a global middleware for setting CORS headers. More...
 
struct  SessionMiddleware
 
struct  InMemoryStore
 InMemoryStore stores all entries in memory. More...
 
struct  FileStore
 
struct  UTF8
 
struct  HTTPParser
 A wrapper for nodejs/http-parser. More...
 
class  query_string
 A class to represent any data coming after the ? in the request URL into key-value pairs. More...
 
struct  returnable
 An abstract class that allows any other class to be returned by a handler. More...
 
class  BaseRule
 A base class for all rules. More...
 
class  CatchallRule
 
class  WebSocketRule
 A rule dealing with websockets. More...
 
struct  RuleParameterTraits
 Allows the user to assign parameters using functions. More...
 
class  DynamicRule
 A rule that can change its parameters during runtime. More...
 
class  TaggedRule
 Default rule created when CROW_ROUTE is called. More...
 
class  Trie
 A search tree. More...
 
class  Blueprint
 A blueprint can be considered a smaller section of a Crow app, specifically where the router is conecerned. More...
 
class  Router
 Handles matching requests to existing rules and upgrade requests. More...
 
struct  SocketAdaptor
 A wrapper for the asio::ip::tcp::socket and asio::ssl::stream. More...
 
struct  SSLAdaptor
 
+ + + + + + + + + + + + + + + + + + + + + + + + +

+Typedefs

+using ssl_context_t = asio::ssl::context
 
+template<typename... Middlewares>
using App = Crow< Middlewares... >
 Alias of Crow<Middlewares...>. Useful if you want a instance of an Crow application that require Middlewares.
 
+using SimpleApp = Crow<>
 Alias of Crow<>. Useful if you want a instance of an Crow application that doesn't require of Middlewares.
 
+using ci_map = std::unordered_multimap< std::string, std::string, ci_hash, ci_key_eq >
 
+using error_code = asio::error_code
 
+using tcp = asio::ip::tcp
 
+typedef struct http_parser http_parser
 
+typedef struct http_parser_settings http_parser_settings
 
+typedef int(* http_data_cb) (http_parser *, const char *at, size_t length)
 
+typedef int(* http_cb) (http_parser *)
 
+ + + + + + + + + + + + + + + + + + + +

+Enumerations

enum class  HTTPMethod : char {
+  DELETE = 0 +, GET +, HEAD +, POST +,
+  PUT +, CONNECT +, OPTIONS +, TRACE +,
+  PATCH +, PURGE +, COPY +, LOCK +,
+  MKCOL +, MOVE +, PROPFIND +, PROPPATCH +,
+  SEARCH +, UNLOCK +, BIND +, REBIND +,
+  UNBIND +, ACL +, REPORT +, MKACTIVITY +,
+  CHECKOUT +, MERGE +, MSEARCH +, NOTIFY +,
+  SUBSCRIBE +, UNSUBSCRIBE +, MKCALENDAR +, LINK +,
+  UNLINK +, SOURCE +, Delete = 0 +, Get +,
+  Head +, Post +, Put +, Connect +,
+  Options +, Trace +, Patch +, Purge +,
+  Copy +, Lock +, MkCol +, Move +,
+  Propfind +, Proppatch +, Search +, Unlock +,
+  Bind +, Rebind +, Unbind +, Acl +,
+  Report +, MkActivity +, Checkout +, Merge +,
+  MSearch +, Notify +, Subscribe +, Unsubscribe +,
+  MkCalendar +, Link +, Unlink +, Source +,
+  InternalMethodCount +
+ }
 
enum  status {
+  CONTINUE = 100 +, SWITCHING_PROTOCOLS = 101 +, OK = 200 +, CREATED = 201 +,
+  ACCEPTED = 202 +, NON_AUTHORITATIVE_INFORMATION = 203 +, NO_CONTENT = 204 +, RESET_CONTENT = 205 +,
+  PARTIAL_CONTENT = 206 +, MULTIPLE_CHOICES = 300 +, MOVED_PERMANENTLY = 301 +, FOUND = 302 +,
+  SEE_OTHER = 303 +, NOT_MODIFIED = 304 +, TEMPORARY_REDIRECT = 307 +, PERMANENT_REDIRECT = 308 +,
+  BAD_REQUEST = 400 +, UNAUTHORIZED = 401 +, FORBIDDEN = 403 +, NOT_FOUND = 404 +,
+  METHOD_NOT_ALLOWED = 405 +, NOT_ACCEPTABLE = 406 +, PROXY_AUTHENTICATION_REQUIRED = 407 +, CONFLICT = 409 +,
+  GONE = 410 +, PAYLOAD_TOO_LARGE = 413 +, UNSUPPORTED_MEDIA_TYPE = 415 +, RANGE_NOT_SATISFIABLE = 416 +,
+  EXPECTATION_FAILED = 417 +, PRECONDITION_REQUIRED = 428 +, TOO_MANY_REQUESTS = 429 +, UNAVAILABLE_FOR_LEGAL_REASONS = 451 +,
+  INTERNAL_SERVER_ERROR = 500 +, NOT_IMPLEMENTED = 501 +, BAD_GATEWAY = 502 +, SERVICE_UNAVAILABLE = 503 +,
+  GATEWAY_TIMEOUT = 504 +, VARIANT_ALSO_NEGOTIATES = 506 +
+ }
 
enum class  ParamType : char {
+  INT +, UINT +, DOUBLE +, STRING +,
+  PATH +, MAX +
+ }
 
enum  http_connection_flags {
+  F_CHUNKED = 1 << 0 +, F_CONNECTION_KEEP_ALIVE = 1 << 1 +, F_CONNECTION_CLOSE = 1 << 2 +, F_TRAILING = 1 << 3 +,
+  F_UPGRADE = 1 << 4 +, F_SKIPBODY = 1 << 5 +, F_CONTENTLENGTH = 1 << 6 +
+ }
 
enum  http_errno
 
enum  state {
+  s_dead = 1 +, s_start_req +, s_req_method +, s_req_spaces_before_url +,
+  s_req_schema +, s_req_schema_slash +, s_req_schema_slash_slash +, s_req_server_start +,
+  s_req_server +, s_req_server_with_at +, s_req_path +, s_req_query_string_start +,
+  s_req_query_string +, s_req_http_start +, s_req_http_H +, s_req_http_HT +,
+  s_req_http_HTT +, s_req_http_HTTP +, s_req_http_I +, s_req_http_IC +,
+  s_req_http_major +, s_req_http_dot +, s_req_http_minor +, s_req_http_end +,
+  s_req_line_almost_done +, s_header_field_start +, s_header_field +, s_header_value_discard_ws +,
+  s_header_value_discard_ws_almost_done +, s_header_value_discard_lws +, s_header_value_start +, s_header_value +,
+  s_header_value_lws +, s_header_almost_done +, s_chunk_size_start +, s_chunk_size +,
+  s_chunk_parameters +, s_chunk_size_almost_done +, s_headers_almost_done +, s_headers_done +,
+  s_chunk_data +, s_chunk_data_almost_done +, s_chunk_data_done +, s_body_identity +,
+  s_body_identity_eof +, s_message_done +
+ }
 
enum  header_states {
+  h_general = 0 +, h_C +, h_CO +, h_CON +,
+  h_matching_connection +, h_matching_proxy_connection +, h_matching_content_length +, h_matching_transfer_encoding +,
+  h_matching_upgrade +, h_connection +, h_content_length +, h_content_length_num +,
+  h_content_length_ws +, h_transfer_encoding +, h_upgrade +, h_matching_transfer_encoding_token_start +,
+  h_matching_transfer_encoding_chunked +, h_matching_transfer_encoding_token +, h_matching_connection_keep_alive +, h_matching_connection_close +,
+  h_transfer_encoding_chunked +, h_connection_keep_alive +, h_connection_close +
+ }
 
enum  http_host_state {
+  s_http_host_dead = 1 +, s_http_userinfo_start +, s_http_userinfo +, s_http_host_start +,
+  s_http_host_v6_start +, s_http_host +, s_http_host_v6 +, s_http_host_v6_end +,
+  s_http_host_v6_zone_start +, s_http_host_v6_zone +, s_http_host_port_start +, s_http_host_port +
+ }
 
enum class  LogLevel {
+  DEBUG = 0 +, INFO +, WARNING +, ERROR +,
+  CRITICAL +, Debug = 0 +, Info +, Warning +,
+  Error +, Critical +
+ }
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

+const std::string crlf ("\r\n")
 
+std::string method_name (HTTPMethod method)
 
+enum state parse_url_char (enum state s, const char ch, http_parser *parser, const char *url_mark, const char *p)
 
+size_t http_parser_execute (http_parser *parser, const http_parser_settings *settings, const char *data, size_t len)
 
+void http_parser_init (http_parser *parser)
 
+const char * http_errno_name (enum http_errno err)
 
+const char * http_errno_description (enum http_errno err)
 
+int http_body_is_final (const struct http_parser *parser)
 
+void http_parser_set_max_header_size (uint32_t size)
 
+template<typename T >
const std::string & get_header_value (const T &headers, const std::string &key)
 Find and return the value associated with the key. (returns an empty string if nothing is found)
 
+int qs_strncmp (const char *s, const char *qs, size_t n)
 
+size_t qs_parse (char *qs, char *qs_kv[], size_t qs_kv_size, bool parse_url)
 
+int qs_decode (char *qs)
 
+char * qs_k2v (const char *key, char *const *qs_kv, size_t qs_kv_size, int nth)
 
+char * qs_scanvalue (const char *key, const char *qs, char *val, size_t val_len)
 
+std::unique_ptr< std::pair< std::string, std::string > > qs_dict_name2kv (const char *dict_name, char *const *qs_kv, size_t qs_kv_size, int nth=0)
 
+ + + + + + + + + + + + + + + +

+Variables

+const char cr = '\r'
 
+const char lf = '\n'
 
+constexpr const char * method_strings []
 
+const std::unordered_map< std::string, std::string > mime_types
 
+constexpr const uint16_t INVALID_BP_ID {((uint16_t)-1)}
 
+const int RULE_SPECIAL_REDIRECT_SLASH = 1
 
+constexpr const char VERSION [] = "master"
 
+

Detailed Description

+

The main namespace of the library. In this namespace is defined the most important classes and functions of the library.

+

Within this namespace, the Crow class, Router class, Connection class, and other are defined.

+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/namespacecrow.js b/1.2/reference/namespacecrow.js new file mode 100644 index 000000000..7e2492134 --- /dev/null +++ b/1.2/reference/namespacecrow.js @@ -0,0 +1,450 @@ +var namespacecrow = +[ + [ "compression", null, [ + [ "algorithm", "compression_8h.html#a63ae5dcf4b8fc685a14110a07279e28d", [ + [ "DEFLATE", "compression_8h.html#a63ae5dcf4b8fc685a14110a07279e28dad9e2819e46ddb632e5cc56455a331954", null ], + [ "GZIP", "compression_8h.html#a63ae5dcf4b8fc685a14110a07279e28da7ef887cefd37d9900750a5e304b140d3", null ] + ] ], + [ "compress_string", "compression_8h.html#a4df206ab03f3bf3c5dca228a5235bb65", null ], + [ "decompress_string", "compression_8h.html#ad143ba98169232ea2b534b51fde7d2c8", null ] + ] ], + [ "detail", null, [ + [ "routing_handler_call_helper", null, [ + [ "call_pair", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair" ], + [ "call_params", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params" ], + [ "call", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call.html", null ], + [ "call< F, NInt, NUint, NDouble, NString, black_magic::S< int64_t, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4" ], + [ "call< F, NInt, NUint, NDouble, NString, black_magic::S< uint64_t, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef" ], + [ "call< F, NInt, NUint, NDouble, NString, black_magic::S< double, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5" ], + [ "call< F, NInt, NUint, NDouble, NString, black_magic::S< std::string, Args1... >, black_magic::S< Args2... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4" ], + [ "call< F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S< Args1... > >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8" ], + [ "Wrapped", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped" ] + ] ], + [ "check_before_handle_arity_3_const", "structcrow_1_1detail_1_1check__before__handle__arity__3__const.html", [ + [ "get", "structcrow_1_1detail_1_1check__before__handle__arity__3__const_1_1get.html", null ] + ] ], + [ "check_before_handle_arity_3", "structcrow_1_1detail_1_1check__before__handle__arity__3.html", [ + [ "get", "structcrow_1_1detail_1_1check__before__handle__arity__3_1_1get.html", null ] + ] ], + [ "check_after_handle_arity_3_const", "structcrow_1_1detail_1_1check__after__handle__arity__3__const.html", [ + [ "get", "structcrow_1_1detail_1_1check__after__handle__arity__3__const_1_1get.html", null ] + ] ], + [ "check_after_handle_arity_3", "structcrow_1_1detail_1_1check__after__handle__arity__3.html", [ + [ "get", "structcrow_1_1detail_1_1check__after__handle__arity__3_1_1get.html", null ] + ] ], + [ "check_global_call_false", "structcrow_1_1detail_1_1check__global__call__false.html", [ + [ "get", "structcrow_1_1detail_1_1check__global__call__false_1_1get.html", null ] + ] ], + [ "is_before_handle_arity_3_impl", "structcrow_1_1detail_1_1is__before__handle__arity__3__impl.html", null ], + [ "is_after_handle_arity_3_impl", "structcrow_1_1detail_1_1is__after__handle__arity__3__impl.html", null ], + [ "is_middleware_global", "structcrow_1_1detail_1_1is__middleware__global.html", null ], + [ "middleware_call_criteria_only_global", "structcrow_1_1detail_1_1middleware__call__criteria__only__global.html", "structcrow_1_1detail_1_1middleware__call__criteria__only__global" ], + [ "middleware_call_criteria_dynamic", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic.html", null ], + [ "middleware_call_criteria_dynamic< false >", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.html", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4" ], + [ "middleware_call_criteria_dynamic< true >", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.html", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4" ], + [ "partial_context", "structcrow_1_1detail_1_1partial__context.html", "structcrow_1_1detail_1_1partial__context" ], + [ "partial_context<>", "structcrow_1_1detail_1_1partial__context_3_4.html", "structcrow_1_1detail_1_1partial__context_3_4" ], + [ "context", "structcrow_1_1detail_1_1context.html", "structcrow_1_1detail_1_1context" ], + [ "middleware_indices", "structcrow_1_1detail_1_1middleware__indices.html", "structcrow_1_1detail_1_1middleware__indices" ], + [ "task_timer", "classcrow_1_1detail_1_1task__timer.html", "classcrow_1_1detail_1_1task__timer" ], + [ "after_handler_call", "middleware_8h.html#a5608f0d89a16e2ba0fe1665ce5010008", null ], + [ "after_handler_call", "middleware_8h.html#a40996d8c8841b5660c504f36b91ba7ea", null ], + [ "after_handlers_call_helper", "middleware_8h.html#a164e2cf51e59306e555db665975f3913", null ], + [ "after_handlers_call_helper", "middleware_8h.html#a7f5f59b3f10c3e7814c658f0b45c10e7", null ], + [ "after_handlers_call_helper", "middleware_8h.html#a172a9273b5ae85873fc54716fbb490af", null ], + [ "before_handler_call", "middleware_8h.html#a539974bbd5c715dda9a318aaf63cf0f2", null ], + [ "before_handler_call", "middleware_8h.html#aa08db03a6d03728487a623804fc2d237", null ], + [ "middleware_call_helper", "middleware_8h.html#adc1c5ae84eb68e35785e7d1f3f09f014", null ], + [ "middleware_call_helper", "middleware_8h.html#a283569c3217695f2fbb11d89fc427139", null ], + [ "wrapped_handler_call", "middleware_8h.html#ac3f9e21fbaf75112165026b34ec6da22", null ], + [ "wrapped_handler_call", "middleware_8h.html#a7ef7e1c30164ce113de572870825d903", null ], + [ "wrapped_handler_call", "middleware_8h.html#aa7b1b74d6dc4ec974bec7ab771c9601e", null ], + [ "wrapped_handler_call", "middleware_8h.html#af75a3e1ff4281b2a9e564ba0e13c6b4a", null ], + [ "wrapped_handler_call", "middleware_8h.html#acf9cea895feacbcb5229873cee9e45f4", null ] + ] ], + [ "json", null, [ + [ "detail", null, [ + [ "r_string", "structcrow_1_1json_1_1detail_1_1r__string.html", "structcrow_1_1json_1_1detail_1_1r__string" ], + [ "operator!=", "json_8h.html#a6355e19700f6ea936e3eb4a492f12fea", null ], + [ "operator!=", "json_8h.html#a264fb7593561920c92734edef8e7d008", null ], + [ "operator!=", "json_8h.html#a81f35f9e2a231426f4c827b791ce305f", null ], + [ "operator<", "json_8h.html#a9e05ef194e02704d74fe40a02f747723", null ], + [ "operator<", "json_8h.html#a6ebe4a1331b93ac4d1e4f1f169388234", null ], + [ "operator<", "json_8h.html#ae20971e8abb83474a7b790d1e8fb7777", null ], + [ "operator==", "json_8h.html#a0c2d17963f4159c72621f429cdf48d95", null ], + [ "operator==", "json_8h.html#a2d67be22770ab4c241c39408d6ff766c", null ], + [ "operator==", "json_8h.html#a9712fe0ae36d479e51bb0ee4ffdc1fc4", null ], + [ "operator>", "json_8h.html#a45d4a8e8e09e2fd22e6b454eb35e1920", null ], + [ "operator>", "json_8h.html#a11f03601163525452ff2d9d08fc669b3", null ], + [ "operator>", "json_8h.html#af676b63abf30ef6d3708798a5204dec8", null ] + ] ], + [ "rvalue", "classcrow_1_1json_1_1rvalue.html", "classcrow_1_1json_1_1rvalue" ], + [ "wvalue", "classcrow_1_1json_1_1wvalue.html", "classcrow_1_1json_1_1wvalue" ], + [ "wvalue_reader", "structcrow_1_1json_1_1wvalue__reader.html", "structcrow_1_1json_1_1wvalue__reader" ], + [ "num_type", "json_8h.html#a0058ebd08b7ec4cd8055d1b2cd4fc527", [ + [ "Signed_integer", "json_8h.html#a0058ebd08b7ec4cd8055d1b2cd4fc527a7d34b6470342f082796613d4c31ae118", null ], + [ "Unsigned_integer", "json_8h.html#a0058ebd08b7ec4cd8055d1b2cd4fc527ae5842290ab3530ab2a35bf0dcaa61608", null ], + [ "Floating_point", "json_8h.html#a0058ebd08b7ec4cd8055d1b2cd4fc527ae16636555d5d2b8a59366e7f28bdc57b", null ], + [ "Null", "json_8h.html#a0058ebd08b7ec4cd8055d1b2cd4fc527abbb93ef26e3c101ff11cdd21cab08a94", null ], + [ "Double_precision_floating_point", "json_8h.html#a0058ebd08b7ec4cd8055d1b2cd4fc527ab5bfea9103f23c9b6688fe6172feadb8", null ] + ] ], + [ "type", "json_8h.html#adb9569a402d1b289a75025c8c96e5d99", [ + [ "Null", "json_8h.html#adb9569a402d1b289a75025c8c96e5d99abbb93ef26e3c101ff11cdd21cab08a94", null ], + [ "False", "json_8h.html#adb9569a402d1b289a75025c8c96e5d99af8320b26d30ab433c5a54546d21f414c", null ], + [ "True", "json_8h.html#adb9569a402d1b289a75025c8c96e5d99af827cf462f62848df37c5e1e94a4da74", null ], + [ "Number", "json_8h.html#adb9569a402d1b289a75025c8c96e5d99ab2ee912b91d69b435159c7c3f6df7f5f", null ], + [ "String", "json_8h.html#adb9569a402d1b289a75025c8c96e5d99a27118326006d3829667a400ad23d5d98", null ], + [ "List", "json_8h.html#adb9569a402d1b289a75025c8c96e5d99a4ee29ca12c7d126654bd0e5275de6135", null ], + [ "Object", "json_8h.html#adb9569a402d1b289a75025c8c96e5d99a497031794414a552435f90151ac3b54b", null ], + [ "Function", "json_8h.html#adb9569a402d1b289a75025c8c96e5d99a86408593c34af77fdd90df932f8b5261", null ] + ] ], + [ "escape", "json_8h.html#a27086e84491472bba7ff876c929f5df3", null ], + [ "escape", "json_8h.html#a98e83fcd8d2e51b3acfc99d868b4e41a", null ], + [ "get_type_str", "json_8h.html#ae63b97ba6f66ef6daf254e00a4b0facb", null ], + [ "load", "json_8h.html#ad995f1379ae1ddc8075cab8185c9a78a", null ], + [ "load", "json_8h.html#a84a2fc9bc21a94b2791271e54879ab0a", null ], + [ "load", "json_8h.html#a59efe2ae1d83ded364cc3ecc143bce85", null ], + [ "load_nocopy_internal", "json_8h.html#a0cd58f45702772a5aac929dec0966a0a", null ], + [ "operator!=", "json_8h.html#a2f0451a26844bed78da38c06d18d76f7", null ], + [ "operator!=", "json_8h.html#a4b737b3cf606bf2e63ed09ceff8ce89a", null ], + [ "operator!=", "json_8h.html#aba197bed8a4a07e34a0733d633b14e9b", null ], + [ "operator!=", "json_8h.html#ac606c21e102f1104500667e9060ee0ed", null ], + [ "operator==", "json_8h.html#a516708ab016de1caa6d3203529929b2e", null ], + [ "operator==", "json_8h.html#a1079ce699fb8174f6f4092b79ef44fc0", null ], + [ "operator==", "json_8h.html#aa9ae087edb7382ba2df19bb5b4b8165b", null ], + [ "operator==", "json_8h.html#a90cbe3f52220c2062156cf256e43c631", null ] + ] ], + [ "multipart", "namespacecrow_1_1multipart.html", "namespacecrow_1_1multipart" ], + [ "mustache", null, [ + [ "detail", null, [ + [ "get_global_template_base_directory_ref", "mustache_8h.html#a738849e5f84dbc8fcf6a63bcac168c09", null ], + [ "get_loader_ref", "mustache_8h.html#a58660424addf4791719562a03b285e0a", null ], + [ "get_template_base_directory_ref", "mustache_8h.html#afe3296362bdc6f187295904755c2103f", null ] + ] ], + [ "invalid_template_exception", "classcrow_1_1mustache_1_1invalid__template__exception.html", "classcrow_1_1mustache_1_1invalid__template__exception" ], + [ "rendered_template", "structcrow_1_1mustache_1_1rendered__template.html", "structcrow_1_1mustache_1_1rendered__template" ], + [ "Action", "structcrow_1_1mustache_1_1_action.html", "structcrow_1_1mustache_1_1_action" ], + [ "template_t", "classcrow_1_1mustache_1_1template__t.html", "classcrow_1_1mustache_1_1template__t" ], + [ "context", "mustache_8h.html#ae1f8ebbbcd4c41b97a2aebb247a123f9", null ], + [ "ActionType", "mustache_8h.html#aeb8da2ae9d8d9fe55f6ab0a7455dd667", [ + [ "Ignore", "mustache_8h.html#aeb8da2ae9d8d9fe55f6ab0a7455dd667afd038fc7f319e48f3115d92bf5bdbef9", null ], + [ "Tag", "mustache_8h.html#aeb8da2ae9d8d9fe55f6ab0a7455dd667ac101058e7ea21bbbf2a5ac893088e90b", null ], + [ "UnescapeTag", "mustache_8h.html#aeb8da2ae9d8d9fe55f6ab0a7455dd667a6a92aa81e0cd0b1c2f77a84226ad4777", null ], + [ "OpenBlock", "mustache_8h.html#aeb8da2ae9d8d9fe55f6ab0a7455dd667a047e46a0bc852354acb31de6a507a3fe", null ], + [ "CloseBlock", "mustache_8h.html#aeb8da2ae9d8d9fe55f6ab0a7455dd667a470529d743a17635308c52dc50efccd8", null ], + [ "ElseBlock", "mustache_8h.html#aeb8da2ae9d8d9fe55f6ab0a7455dd667ab82f53ea35520be1175d4764c22d2b30", null ], + [ "Partial", "mustache_8h.html#aeb8da2ae9d8d9fe55f6ab0a7455dd667a44ffd38a6dea695cbe2b34efdcc6cf27", null ] + ] ], + [ "compile", "mustache_8h.html#a5823e2be647059121cc4f0329e44741a", null ], + [ "default_loader", "mustache_8h.html#a7e8660fbdeeb994a1f00c704b469c792", null ], + [ "load", "mustache_8h.html#abe44de50c382e0d39e7ef5b7d5057ca6", null ], + [ "load_text", "mustache_8h.html#a8db3aff497ff60b32321fc0a16274576", null ], + [ "load_text_unsafe", "mustache_8h.html#a5c27c8fa1561611202419d8c2f6c80cc", null ], + [ "load_unsafe", "mustache_8h.html#af883f129665fb698bc4da7659d0b0841", null ], + [ "set_base", "mustache_8h.html#a88cf75099968de883a8e2bf14ce6d1cb", null ], + [ "set_global_base", "mustache_8h.html#a5cdb6a51dda64e4916a8cb49358ac0b6", null ], + [ "set_loader", "mustache_8h.html#a064911bc597a2a849f008b50cdead53e", null ] + ] ], + [ "session", null, [ + [ "multi_value", "structcrow_1_1session_1_1multi__value.html", "structcrow_1_1session_1_1multi__value" ], + [ "ExpirationTracker", "structcrow_1_1session_1_1_expiration_tracker.html", "structcrow_1_1session_1_1_expiration_tracker" ], + [ "CachedSession", "structcrow_1_1session_1_1_cached_session.html", "structcrow_1_1session_1_1_cached_session" ] + ] ], + [ "websocket", "namespacecrow_1_1websocket.html", "namespacecrow_1_1websocket" ], + [ "Crow", "classcrow_1_1_crow.html", "classcrow_1_1_crow" ], + [ "ci_hash", "structcrow_1_1ci__hash.html", "structcrow_1_1ci__hash" ], + [ "ci_key_eq", "structcrow_1_1ci__key__eq.html", "structcrow_1_1ci__key__eq" ], + [ "routing_handle_result", "structcrow_1_1routing__handle__result.html", "structcrow_1_1routing__handle__result" ], + [ "Connection", "classcrow_1_1_connection.html", "classcrow_1_1_connection" ], + [ "http_parser", "structcrow_1_1http__parser.html", "structcrow_1_1http__parser" ], + [ "http_parser_settings", "structcrow_1_1http__parser__settings.html", "structcrow_1_1http__parser__settings" ], + [ "request", "structcrow_1_1request.html", "structcrow_1_1request" ], + [ "response", "structcrow_1_1response.html", "structcrow_1_1response" ], + [ "Server", "classcrow_1_1_server.html", "classcrow_1_1_server" ], + [ "ILogHandler", "classcrow_1_1_i_log_handler.html", "classcrow_1_1_i_log_handler" ], + [ "CerrLogHandler", "classcrow_1_1_cerr_log_handler.html", "classcrow_1_1_cerr_log_handler" ], + [ "logger", "classcrow_1_1logger.html", "classcrow_1_1logger" ], + [ "ILocalMiddleware", "structcrow_1_1_i_local_middleware.html", "structcrow_1_1_i_local_middleware" ], + [ "CookieParser", "structcrow_1_1_cookie_parser.html", "structcrow_1_1_cookie_parser" ], + [ "CORSRules", "structcrow_1_1_c_o_r_s_rules.html", "structcrow_1_1_c_o_r_s_rules" ], + [ "CORSHandler", "structcrow_1_1_c_o_r_s_handler.html", "structcrow_1_1_c_o_r_s_handler" ], + [ "SessionMiddleware", "structcrow_1_1_session_middleware.html", "structcrow_1_1_session_middleware" ], + [ "InMemoryStore", "structcrow_1_1_in_memory_store.html", "structcrow_1_1_in_memory_store" ], + [ "FileStore", "structcrow_1_1_file_store.html", "structcrow_1_1_file_store" ], + [ "UTF8", "structcrow_1_1_u_t_f8.html", "structcrow_1_1_u_t_f8" ], + [ "HTTPParser", "structcrow_1_1_h_t_t_p_parser.html", "structcrow_1_1_h_t_t_p_parser" ], + [ "query_string", "classcrow_1_1query__string.html", "classcrow_1_1query__string" ], + [ "returnable", "structcrow_1_1returnable.html", "structcrow_1_1returnable" ], + [ "BaseRule", "classcrow_1_1_base_rule.html", "classcrow_1_1_base_rule" ], + [ "CatchallRule", "classcrow_1_1_catchall_rule.html", "classcrow_1_1_catchall_rule" ], + [ "WebSocketRule", "classcrow_1_1_web_socket_rule.html", "classcrow_1_1_web_socket_rule" ], + [ "RuleParameterTraits", "structcrow_1_1_rule_parameter_traits.html", "structcrow_1_1_rule_parameter_traits" ], + [ "DynamicRule", "classcrow_1_1_dynamic_rule.html", "classcrow_1_1_dynamic_rule" ], + [ "TaggedRule", "classcrow_1_1_tagged_rule.html", "classcrow_1_1_tagged_rule" ], + [ "Trie", "classcrow_1_1_trie.html", "classcrow_1_1_trie" ], + [ "Blueprint", "classcrow_1_1_blueprint.html", "classcrow_1_1_blueprint" ], + [ "Router", "classcrow_1_1_router.html", "classcrow_1_1_router" ], + [ "SocketAdaptor", "structcrow_1_1_socket_adaptor.html", "structcrow_1_1_socket_adaptor" ], + [ "SSLAdaptor", "structcrow_1_1_s_s_l_adaptor.html", "structcrow_1_1_s_s_l_adaptor" ], + [ "App", "namespacecrow.html#a153c1bf24903d1a8629ef6eaf045110b", null ], + [ "ci_map", "namespacecrow.html#a9090432313cd58380727a6c4384ee792", null ], + [ "error_code", "namespacecrow.html#af8d81eb0a66cd60f10fb6182fac76ff1", null ], + [ "http_cb", "namespacecrow.html#ac8d886c5987c6c3517844254c64702d8", null ], + [ "http_data_cb", "namespacecrow.html#a170dd039834658eb49e3fc875cc7de2a", null ], + [ "http_parser", "namespacecrow.html#a924fefc9c36b2db0e5d33a7d411282df", null ], + [ "http_parser_settings", "namespacecrow.html#a363ac66c79459472e2af679f99966d0f", null ], + [ "SimpleApp", "namespacecrow.html#a3603179c9794548cac2c9990685178b4", null ], + [ "ssl_context_t", "namespacecrow.html#abdecc4861f896188f2c6ce6ec362d403", null ], + [ "tcp", "namespacecrow.html#a65f96f2358b6394677de6a13301e9e69", null ], + [ "header_states", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660ed", [ + [ "h_general", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660edaf87086fb007768e9efef33a437a88e43", null ], + [ "h_C", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda515ecfb573b179b0e24dd00cbc7a89f0", null ], + [ "h_CO", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda906a558bb5dc4ebe0625f1a88cef34d3", null ], + [ "h_CON", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda4e7d8f10a6a54cb2b230611f4a50c04d", null ], + [ "h_matching_connection", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda25abca0c62b09298e03bb35bb0d1710b", null ], + [ "h_matching_proxy_connection", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda8d9bbcc8863353fc01d5edf2aa3fa446", null ], + [ "h_matching_content_length", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660edacc7bcb87d42ef38c5382d65b982047dd", null ], + [ "h_matching_transfer_encoding", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda121255b93b3c09430864db3bfafa1024", null ], + [ "h_matching_upgrade", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda45dc51062a550b0d66d7e7e18ce5d5e5", null ], + [ "h_connection", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660edaa4e048cf97537459aa55374e8a05850b", null ], + [ "h_content_length", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660edadd29916b27b202d0978aac177be25239", null ], + [ "h_content_length_num", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660edaf413528456bd997e3bb20053d4bd1829", null ], + [ "h_content_length_ws", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda63ef8d6678cf7d802e7136a01ca1c9ed", null ], + [ "h_transfer_encoding", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda2b451501568ed19813ed5fed394cd024", null ], + [ "h_upgrade", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda0802709e79fb35e6261b3427124b421f", null ], + [ "h_matching_transfer_encoding_token_start", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda42ad044a7ad200def86396ff72046d74", null ], + [ "h_matching_transfer_encoding_chunked", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda8439d492c5da6ed2b5d60c575f9b1b39", null ], + [ "h_matching_transfer_encoding_token", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda9b9b1cc555e3f32c02c2c29254c725e5", null ], + [ "h_matching_connection_keep_alive", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda7fd544e9de8e4bb7cf3e98fa39a923b4", null ], + [ "h_matching_connection_close", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda18f335af664c0ccc6d36cffe239edad5", null ], + [ "h_transfer_encoding_chunked", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda9c268a1e11ec491387b59585372d4ad2", null ], + [ "h_connection_keep_alive", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660eda8ff3d778ccc85bb6fd7ca9cb4d03668f", null ], + [ "h_connection_close", "namespacecrow.html#a3f9dce1dea158e8997e5c79561e660edae15064c99fc2f07a06ec795c378efd5b", null ] + ] ], + [ "http_connection_flags", "namespacecrow.html#ace318a1645dc41d46e6b7bf1470e000f", [ + [ "F_CHUNKED", "namespacecrow.html#ace318a1645dc41d46e6b7bf1470e000fab7d4c78c3acafdc959b2029ee7d3d726", null ], + [ "F_CONNECTION_KEEP_ALIVE", "namespacecrow.html#ace318a1645dc41d46e6b7bf1470e000fa29ac3060dc7313e3adf7e46fb90ac441", null ], + [ "F_CONNECTION_CLOSE", "namespacecrow.html#ace318a1645dc41d46e6b7bf1470e000fa8546968a8575638a3a43c6e5e028d0be", null ], + [ "F_TRAILING", "namespacecrow.html#ace318a1645dc41d46e6b7bf1470e000fa1ce6101990da561f3aff08c2e53c01f9", null ], + [ "F_UPGRADE", "namespacecrow.html#ace318a1645dc41d46e6b7bf1470e000fa7f3716810d80eabe0cc216c42305ac73", null ], + [ "F_SKIPBODY", "namespacecrow.html#ace318a1645dc41d46e6b7bf1470e000faeef386931f6a052decf071c1b5c15ed8", null ], + [ "F_CONTENTLENGTH", "namespacecrow.html#ace318a1645dc41d46e6b7bf1470e000fafa15be75dca505aacdf5d2f2f99e0faa", null ] + ] ], + [ "http_errno", "namespacecrow.html#a500a501f00a9398f69e054b30ef011cd", null ], + [ "http_host_state", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0d", [ + [ "s_http_host_dead", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0dadad6faee5de3ef26a56e4d5450cd8588", null ], + [ "s_http_userinfo_start", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0daa34ae7256f1f3d4d370ccb8a49558e15", null ], + [ "s_http_userinfo", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0daa5d562c698895e0de54a998d2177e7b6", null ], + [ "s_http_host_start", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0dab8aea2e2fe8a6d77d766f3166341575f", null ], + [ "s_http_host_v6_start", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0da852b7e1f2d0f1f1d61d270cafac6808b", null ], + [ "s_http_host", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0da882814ab7656cc07edfa3a862fe3ba8d", null ], + [ "s_http_host_v6", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0da7e2b3543ed53eb50742e5cb3982a1d65", null ], + [ "s_http_host_v6_end", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0da94539b38bdfce2e948613b7e718b13af", null ], + [ "s_http_host_v6_zone_start", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0daa166e0a42f4c1c9d786ab823d97cc1d3", null ], + [ "s_http_host_v6_zone", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0da202a5bc99c3f1b9d7525b2f43d1b4d39", null ], + [ "s_http_host_port_start", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0da9a69af78ba46a5ec27035ceeb2607445", null ], + [ "s_http_host_port", "namespacecrow.html#a920284a6db56250dd828ce47ddae0c0da56344313c2d6f34acac3ba67348a4fde", null ] + ] ], + [ "HTTPMethod", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4", [ + [ "DELETE", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a32f68a60cef40faedbc6af20298c1a1e", null ], + [ "GET", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a7528035a93ee69cedb1dbddb2f0bfcc8", null ], + [ "HEAD", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ae15e216fc1c639f787b1231ecdfa1bf8", null ], + [ "POST", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4aa02439ec229d8be0e74b0c1602392310", null ], + [ "PUT", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a3e75383a5992a6d15fb81e872e46e256", null ], + [ "CONNECT", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ab57e2519e26151feacdbe52076bc39ec", null ], + [ "OPTIONS", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a164dd62adb30ca051b5289672a572f9b", null ], + [ "TRACE", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a2d3e4144aa384b18849ab9a8abad74d6", null ], + [ "PATCH", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a63bc9a3997d66d835d9f3ec29451407d", null ], + [ "PURGE", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4af29973ceeff9e3672f9827d2b3615283", null ], + [ "COPY", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ae8606d021da140a92c7eba8d9b8af84f", null ], + [ "LOCK", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4af510b97de4ace11844b85f23d0fc012f", null ], + [ "MKCOL", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4aa02411acd2f70fdd738894061f7d87c1", null ], + [ "MOVE", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4af7f93635f8e193a924ae4a691bb66b8f", null ], + [ "PROPFIND", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a599a96a4db707f1cdcb9affd34ca8d72", null ], + [ "PROPPATCH", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4afe20db8c57ee09e59fcc6ae857443e02", null ], + [ "SEARCH", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a0f544d682c3a664870f025f48c4b04b5", null ], + [ "UNLOCK", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a08f473e8e1515801cb25e584a6832f34", null ], + [ "BIND", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a5c179f2c26f1208979f95a11f886c7c6", null ], + [ "REBIND", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a165c797424624799cb60ff4fe6d5164c", null ], + [ "UNBIND", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a82c3132801d8e123a351387716e61247", null ], + [ "ACL", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a5bec55d452dbea99476cd51a1c821b8a", null ], + [ "REPORT", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ad02a38d7ff75e9aed743437fd9539a44", null ], + [ "MKACTIVITY", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4aabc1e2b31f1af0e5b07860bd52ac5841", null ], + [ "CHECKOUT", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ae488f04180a5804feba48dbc87f0787d", null ], + [ "MERGE", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a97c51054c5ed46d2f88641ac57ff6347", null ], + [ "MSEARCH", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a1a05a7da73d0e7a957db62621927ce17", null ], + [ "NOTIFY", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a9d087bfb809874e1b3e9adcbae8ca761", null ], + [ "SUBSCRIBE", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a45b73ef479821e71be9f69a190f2bb86", null ], + [ "UNSUBSCRIBE", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a62b18b8274e34fd701d0b684a32c633f", null ], + [ "MKCALENDAR", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a2f79dc519744e08cebb04946a6b9e9f9", null ], + [ "LINK", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a58c0a0e97e6d2f615bc264c2775fda44", null ], + [ "UNLINK", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4aa07e75cb3ec757003bb6b1284024135b", null ], + [ "SOURCE", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ae60b4854b44ccfb2d92aa6f035171bb4", null ], + [ "Delete", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4af2a6c498fb90ee345d997f888fce3b18", null ], + [ "Get", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ac55582518cba2c464f29f5bae1c68def", null ], + [ "Head", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a98921133d10fbdb0fb6dbb7b2648befe", null ], + [ "Post", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a03d947a2158373c3b9d74325850cb8b9", null ], + [ "Put", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ad0bf1810982e9728fcf3ac444a015373", null ], + [ "Connect", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a49ab28040dfa07f53544970c6d147e1e", null ], + [ "Options", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4adae8ace18bdcbcc6ae5aece263e14fe8", null ], + [ "Trace", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4add4ec0ac4e58f7c32a01244ae91150b1", null ], + [ "Patch", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a156e10596fdc76ee5300bab931d89c0f", null ], + [ "Purge", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ad67c704564d7976991e2f23e4315ccfd", null ], + [ "Copy", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a5fb63579fc981698f97d55bfecb213ea", null ], + [ "Lock", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ab485167c5b0e59d47009a16f90fe2659", null ], + [ "MkCol", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a0253c02f8d9e5333b541145dfbfc35a0", null ], + [ "Move", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a6bc362dbf494c61ea117fe3c71ca48a5", null ], + [ "Propfind", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a0d5bba9a5baaf04c7cda36449ebed7bf", null ], + [ "Proppatch", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a29a53f1d67dd56d8b58a48dc93eb246b", null ], + [ "Search", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a13348442cc6a27032d2b4aa28b75a5d3", null ], + [ "Unlock", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a7e7123b0d269ad5d9ec8d12c52a8ed8a", null ], + [ "Bind", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a0b172674284d79079624051d2ae11581", null ], + [ "Rebind", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a2c8b844cbfb121428d378232606d6b47", null ], + [ "Unbind", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a4bffa5083d48d52f00eb873b6e136d5f", null ], + [ "Acl", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ad740ec45faa5dde148d59cf627722130", null ], + [ "Report", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a4b1b4dc8cf38b3c64b1d657da8f5ac8c", null ], + [ "MkActivity", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a7860be0b5977633991049ba7e2db928a", null ], + [ "Checkout", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a6ff063fbc860a79759a7369ac32cee22", null ], + [ "Merge", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a68be4837f6c739877233e527a996dd00", null ], + [ "MSearch", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a2cbcb616339472c9cc37591f3b95372e", null ], + [ "Notify", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4aaaf9ed605d0193362321ba0def15c9b7", null ], + [ "Subscribe", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ab26917587d98330d93f87808fc9d7267", null ], + [ "Unsubscribe", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a4182c8f19d40c7ca236a5f4f83faeb6b", null ], + [ "MkCalendar", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4afd8731b039d3bcb16908de23a2932d9a", null ], + [ "Link", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a97e7c9a7d06eac006a28bf05467fcc8b", null ], + [ "Unlink", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4ac1a39b6a60f8b2f87e23d60ab649d994", null ], + [ "Source", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4af31bbdd1b3e85bccd652680e16935819", null ], + [ "InternalMethodCount", "namespacecrow.html#afe3a72ef7c3edbf71d0bceacf02517c4a783e32402715ea977e4e06eb22b370b6", null ] + ] ], + [ "LogLevel", "namespacecrow.html#ad07dc32e163caa516aa1225a1ec4afe4", [ + [ "DEBUG", "namespacecrow.html#ad07dc32e163caa516aa1225a1ec4afe4adc30ec20708ef7b0f641ef78b7880a15", null ], + [ "INFO", "namespacecrow.html#ad07dc32e163caa516aa1225a1ec4afe4a551b723eafd6a31d444fcb2f5920fbd3", null ], + [ "WARNING", "namespacecrow.html#ad07dc32e163caa516aa1225a1ec4afe4a059e9861e0400dfbe05c98a841f3f96b", null ], + [ "ERROR", "namespacecrow.html#ad07dc32e163caa516aa1225a1ec4afe4abb1ca97ec761fc37101737ba0aa2e7c5", null ], + [ "CRITICAL", "namespacecrow.html#ad07dc32e163caa516aa1225a1ec4afe4a99cd1c61610c76a57cb8d10d6df6b870", null ], + [ "Debug", "namespacecrow.html#ad07dc32e163caa516aa1225a1ec4afe4aa603905470e2a5b8c13e96b579ef0dba", null ], + [ "Info", "namespacecrow.html#ad07dc32e163caa516aa1225a1ec4afe4a4059b0251f66a18cb56f544728796875", null ], + [ "Warning", "namespacecrow.html#ad07dc32e163caa516aa1225a1ec4afe4a0eaadb4fcb48a0a0ed7bc9868be9fbaa", null ], + [ "Error", "namespacecrow.html#ad07dc32e163caa516aa1225a1ec4afe4a902b0d55fddef6f8d651fe1035b7d4bd", null ], + [ "Critical", "namespacecrow.html#ad07dc32e163caa516aa1225a1ec4afe4a278d01e5af56273bae1bb99a98b370cd", null ] + ] ], + [ "ParamType", "namespacecrow.html#a6ea84108a731cd6a42a55737c9970d5f", [ + [ "INT", "namespacecrow.html#a6ea84108a731cd6a42a55737c9970d5fa53f93baa3057821107c750323892fa92", null ], + [ "UINT", "namespacecrow.html#a6ea84108a731cd6a42a55737c9970d5fa3351504090a741e69da641a42e00da80", null ], + [ "DOUBLE", "namespacecrow.html#a6ea84108a731cd6a42a55737c9970d5fafd3e4ece78a7d422280d5ed379482229", null ], + [ "STRING", "namespacecrow.html#a6ea84108a731cd6a42a55737c9970d5fa63b588d5559f64f89a416e656880b949", null ], + [ "PATH", "namespacecrow.html#a6ea84108a731cd6a42a55737c9970d5fa5ffb5f0d0de78321df46fc7c93ca64a3", null ], + [ "MAX", "namespacecrow.html#a6ea84108a731cd6a42a55737c9970d5fa26a4b44a837bf97b972628509912b4a5", null ] + ] ], + [ "state", "namespacecrow.html#af3683f183a8154824b3e77db7769a035", [ + [ "s_dead", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a6f457a0b5a3dcd69d76a265151a1d8ad", null ], + [ "s_start_req", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a6f2fbe258aaec2de63dedbc86fe51d0d", null ], + [ "s_req_method", "namespacecrow.html#af3683f183a8154824b3e77db7769a035ad6bec0a97fed8d010a4c0540a3b6bb49", null ], + [ "s_req_spaces_before_url", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a551f46283343164101131f5d32ce6a49", null ], + [ "s_req_schema", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a53fe02c624c9f56538641b8052e26578", null ], + [ "s_req_schema_slash", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a0ef9378606e88b0aa793d15e1e893477", null ], + [ "s_req_schema_slash_slash", "namespacecrow.html#af3683f183a8154824b3e77db7769a035aa61fc69931f3e2be09f2427c3dd81986", null ], + [ "s_req_server_start", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a4c4d2db8611e5e683521bdc2ee4a87f2", null ], + [ "s_req_server", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a6575d3343b1930eb8f457aa8eb3f743e", null ], + [ "s_req_server_with_at", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a37a603acbe6557edbbaea8bcb7a969ad", null ], + [ "s_req_path", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a9de78cb29653ee80a58cb38cdfa4ee14", null ], + [ "s_req_query_string_start", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a1a8a06bc10b835d77010c89d9abd910d", null ], + [ "s_req_query_string", "namespacecrow.html#af3683f183a8154824b3e77db7769a035aa4bea65ec09b163d1e5eda520ddab207", null ], + [ "s_req_http_start", "namespacecrow.html#af3683f183a8154824b3e77db7769a035ad7f9bf23f11f5115d4a9917959b3ceda", null ], + [ "s_req_http_H", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a6e56cc8a122a9215795d0b91e3a0acbe", null ], + [ "s_req_http_HT", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a5a6bba2702871884527bfbfbf638a264", null ], + [ "s_req_http_HTT", "namespacecrow.html#af3683f183a8154824b3e77db7769a035aad5b0d0d564638c3eaa49e9cfd48ef45", null ], + [ "s_req_http_HTTP", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a65b0b4b07a85e830650956f9bf2aa5c2", null ], + [ "s_req_http_I", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a9ff15c49b19ad13cf6c0bf5b0f02724b", null ], + [ "s_req_http_IC", "namespacecrow.html#af3683f183a8154824b3e77db7769a035ad86d7906fb080fa0fb73008334f2fa82", null ], + [ "s_req_http_major", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a9c6a58d43d0961f2cedc1735a209ac6f", null ], + [ "s_req_http_dot", "namespacecrow.html#af3683f183a8154824b3e77db7769a035aba4b7f096fe2909beb19adca8790fbb9", null ], + [ "s_req_http_minor", "namespacecrow.html#af3683f183a8154824b3e77db7769a035abb8c5a16ad1450f2b980dc4a12ae3e57", null ], + [ "s_req_http_end", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a395957f606e53997c93035187c3c5e3d", null ], + [ "s_req_line_almost_done", "namespacecrow.html#af3683f183a8154824b3e77db7769a035ad180b64ac2b6a18cb63f3741d9555a5d", null ], + [ "s_header_field_start", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a68761da5f3673f20d8ee36d47e5b16fa", null ], + [ "s_header_field", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a3712d831a741db722152b7b956e2bfc1", null ], + [ "s_header_value_discard_ws", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a138e3cff06f29c223df8a755ed15e7a2", null ], + [ "s_header_value_discard_ws_almost_done", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a056d79e3cf170f63d6b3c82d23d64dce", null ], + [ "s_header_value_discard_lws", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a25c34ce845c6ec63dc9627fdfc4f4739", null ], + [ "s_header_value_start", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a026d65a36e6c9c13b3bf3be8081f9be0", null ], + [ "s_header_value", "namespacecrow.html#af3683f183a8154824b3e77db7769a035aaf613f0d885e13bbfa331817acce56af", null ], + [ "s_header_value_lws", "namespacecrow.html#af3683f183a8154824b3e77db7769a035aa148b954cc8659aea0df9011c9301ceb", null ], + [ "s_header_almost_done", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a44792f187e513c48eee00d8418ec75b2", null ], + [ "s_chunk_size_start", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a11779f7ccdaa7d5033b4b6fdae04d2ba", null ], + [ "s_chunk_size", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a3f33db95f05de0c9a1e760d432470973", null ], + [ "s_chunk_parameters", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a190a73f676b005463ee9c4698390f129", null ], + [ "s_chunk_size_almost_done", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a68949314ff53417470b24170f2134913", null ], + [ "s_headers_almost_done", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a971b230de2d497d4b279454a6f1576e2", null ], + [ "s_headers_done", "namespacecrow.html#af3683f183a8154824b3e77db7769a035aa9dd932a2affc469260c0c70e1e58b5f", null ], + [ "s_chunk_data", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a83fde3fd2b2ce7dd92032727611c882c", null ], + [ "s_chunk_data_almost_done", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a2922196e969caf4295b88ab1409cb2ec", null ], + [ "s_chunk_data_done", "namespacecrow.html#af3683f183a8154824b3e77db7769a035adc071f4cbd9d8c435e63bd3ad18febf1", null ], + [ "s_body_identity", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a00310ada2a3c20b950e6d6310700c569", null ], + [ "s_body_identity_eof", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a0620dd59a431733919fefc81746d6c7d", null ], + [ "s_message_done", "namespacecrow.html#af3683f183a8154824b3e77db7769a035a62d6e16b3c689b7a1fecc3fb337c6e9a", null ] + ] ], + [ "status", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2", [ + [ "CONTINUE", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a473f2f24e8c923537fb87b5d3e3ddd1a", null ], + [ "SWITCHING_PROTOCOLS", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a515df58240b20796066ffadd186ca4e5", null ], + [ "OK", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2abf75a89ed4b41a208bce65376c6a2218", null ], + [ "CREATED", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2aaaef35bbfd12ebea9c8a708dce25a620", null ], + [ "ACCEPTED", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2add6aa560363c5206b76df02a698bdaf1", null ], + [ "NON_AUTHORITATIVE_INFORMATION", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2afdb182b863f49ea57ec1bde6e2d99eba", null ], + [ "NO_CONTENT", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a7ba6f58b2b3331b37b91cb562a8cc296", null ], + [ "RESET_CONTENT", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2aae353d39be103077cd80b41f39c73deb", null ], + [ "PARTIAL_CONTENT", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2abad2df9a126f98eb3e889d6fd83a74c6", null ], + [ "MULTIPLE_CHOICES", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a36eadfd0ea37bcb89c012ce41702c939", null ], + [ "MOVED_PERMANENTLY", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2aead42cbdf2f1aa04422e0b3cabd61ae6", null ], + [ "FOUND", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2af262b382f021488bb913d9cf179ccd6e", null ], + [ "SEE_OTHER", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a0db092278813afae4ce28611ac6deae2", null ], + [ "NOT_MODIFIED", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2aa5c1413df923fc24345cc479cdb3789e", null ], + [ "TEMPORARY_REDIRECT", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2af01b5584cbcde1b1c9a6717f96a29223", null ], + [ "PERMANENT_REDIRECT", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2ae3f6c6e0ee7b2c99e0e5165c8f2e007b", null ], + [ "BAD_REQUEST", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2aea8e1cf302f8f6b1f5e3365555f71976", null ], + [ "UNAUTHORIZED", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2aa4c229683e23e7ce3de0c6f27f1dfd34", null ], + [ "FORBIDDEN", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a05240c5b2cb4e0763c5d978dbb4983b8", null ], + [ "NOT_FOUND", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a6a8e1449312141170a8dca8e03daefde", null ], + [ "METHOD_NOT_ALLOWED", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a0c13e49395e3eec357ff5e24e6d5c976", null ], + [ "NOT_ACCEPTABLE", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2af864cd6308323d902ab1a55e5e140f50", null ], + [ "PROXY_AUTHENTICATION_REQUIRED", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a4d63e712f283450fb3216cc4eed26e2e", null ], + [ "CONFLICT", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a635a1496ca032ba8b5cef9557cefeb40", null ], + [ "GONE", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2af7917fa7182fbd44a677ff497b4e0581", null ], + [ "PAYLOAD_TOO_LARGE", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2aa58af15ca6e403c5ebdf487528b25181", null ], + [ "UNSUPPORTED_MEDIA_TYPE", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a169ba79197aad876ca5314d6eefebb59", null ], + [ "RANGE_NOT_SATISFIABLE", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2af2ac4d9dd8af2c6830a5c05c3ddd1883", null ], + [ "EXPECTATION_FAILED", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2ad93870a374394e469f3a91be54ef0f3a", null ], + [ "PRECONDITION_REQUIRED", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a0b61a6d0a97c0e433e194d6a927569b8", null ], + [ "TOO_MANY_REQUESTS", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a5cd8322fa600e7b84b62d4f231e23542", null ], + [ "UNAVAILABLE_FOR_LEGAL_REASONS", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2af85b2be08a05b35370dd31bc8bbb31e2", null ], + [ "INTERNAL_SERVER_ERROR", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a831d1d03d432e5bc39f2867443c2c039", null ], + [ "NOT_IMPLEMENTED", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2aa1746b1ff431505dfb1ebf1833595bbb", null ], + [ "BAD_GATEWAY", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a8bdf8e1a9f962b56c67e7566d456677f", null ], + [ "SERVICE_UNAVAILABLE", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a677e9fc48ff03728ef8315d1cfb1fff9", null ], + [ "GATEWAY_TIMEOUT", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a9b0687f77d4aacb25c799220daac9086", null ], + [ "VARIANT_ALSO_NEGOTIATES", "namespacecrow.html#aa3ae5c0994dff8425d7515e2806180d2a95ff44a69992d4043ef2c93dc3468340", null ] + ] ], + [ "crlf", "namespacecrow.html#a664043b97bc65e838a04a35f2f4ce4b9", null ], + [ "get_header_value", "namespacecrow.html#ac0940ae1e094df6107d3a2604537279a", null ], + [ "http_body_is_final", "namespacecrow.html#ae7c980723de3eaf3184cae9e2f3a5a68", null ], + [ "http_errno_description", "namespacecrow.html#a96888f86f6198dd36626ff9eddd5a993", null ], + [ "http_errno_name", "namespacecrow.html#ad5b6797a3a6f48a7a9278e2248ac6e13", null ], + [ "http_parser_execute", "namespacecrow.html#a74a220575597e34e963b9e4dd3d72ab5", null ], + [ "http_parser_init", "namespacecrow.html#a9827c30b69b8d145960be294cc637421", null ], + [ "http_parser_set_max_header_size", "namespacecrow.html#a5cdaa545f75beccb7dfdecccdb7f5dfc", null ], + [ "method_name", "namespacecrow.html#a2e95f26db5041c7f322bd38c2de6a6b1", null ], + [ "parse_url_char", "namespacecrow.html#a92a181e0dc142c79e06ac976e4696024", null ], + [ "qs_decode", "namespacecrow.html#a14fbbb7c98eecbb8d718dbc3d4ca5d96", null ], + [ "qs_dict_name2kv", "namespacecrow.html#ac5e8f29b313f59a8fd17a7c599173edf", null ], + [ "qs_k2v", "namespacecrow.html#ad97a80f336978f6d8594e135ee69ceda", null ], + [ "qs_parse", "namespacecrow.html#a3b114d3a6123223c5280ee85cc46fdc5", null ], + [ "qs_scanvalue", "namespacecrow.html#a7cb7caaae568c2c55779c4a02fd6cf52", null ], + [ "qs_strncmp", "namespacecrow.html#adcc1e7c149f03db601f2ca22a827f399", null ], + [ "cr", "namespacecrow.html#a348a7fc1fc788f1974ad34d1b1cf5b9e", null ], + [ "INVALID_BP_ID", "namespacecrow.html#af15d23b18fca6cb5f5cf45be0e43db71", null ], + [ "lf", "namespacecrow.html#ad64fc935fb542bd04fd30bf7708413cb", null ], + [ "method_strings", "namespacecrow.html#aa7c30f564257452fb6e9c074351f53d1", null ], + [ "mime_types", "namespacecrow.html#ae3bc69c854fcab2bbf5a8c628fbe6894", null ], + [ "RULE_SPECIAL_REDIRECT_SLASH", "namespacecrow.html#a73062c5f5d45cb57eb32fd8a3f916132", null ], + [ "VERSION", "namespacecrow.html#abb19b56c65f91e49d56abadf3fc947f1", null ] +]; \ No newline at end of file diff --git a/1.2/reference/namespacecrow_1_1multipart.html b/1.2/reference/namespacecrow_1_1multipart.html new file mode 100644 index 000000000..173a68740 --- /dev/null +++ b/1.2/reference/namespacecrow_1_1multipart.html @@ -0,0 +1,170 @@ + + + + + + + + Crow: crow::multipart Namespace Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::multipart Namespace Reference
+
+
+ +

Encapsulates anything related to processing and organizing multipart/xyz messages. +More...

+ + + + + + + + + + + +

+Classes

struct  header
 The first part in a section, contains metadata about the part. More...
 
struct  part
 One part of the multipart message. More...
 
struct  message
 The parsed multipart request/response. More...
 
+ + + + + + + +

+Typedefs

+using mph_map = std::unordered_multimap< std::string, header, ci_hash, ci_key_eq >
 Multipart header map (key is header key).
 
+using mp_map = std::unordered_multimap< std::string, part, ci_hash, ci_key_eq >
 Multipart map (key is the name parameter).
 
+ + + + + + + + + +

+Functions

+template<typename O , typename T >
const O & get_header_value_object (const T &headers, const std::string &key)
 Find and return the value object associated with the key. (returns an empty class if nothing is found)
 
+template<typename T >
const headerget_header_object (const T &headers, const std::string &key)
 Same as get_header_value_object() but for multipart::header.
 
+ + + +

+Variables

+const std::string dd = "--"
 
+

Detailed Description

+

Encapsulates anything related to processing and organizing multipart/xyz messages.

+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/namespacecrow_1_1multipart.js b/1.2/reference/namespacecrow_1_1multipart.js new file mode 100644 index 000000000..9efc07a60 --- /dev/null +++ b/1.2/reference/namespacecrow_1_1multipart.js @@ -0,0 +1,11 @@ +var namespacecrow_1_1multipart = +[ + [ "header", "structcrow_1_1multipart_1_1header.html", "structcrow_1_1multipart_1_1header" ], + [ "part", "structcrow_1_1multipart_1_1part.html", "structcrow_1_1multipart_1_1part" ], + [ "message", "structcrow_1_1multipart_1_1message.html", "structcrow_1_1multipart_1_1message" ], + [ "mp_map", "namespacecrow_1_1multipart.html#a071bb6d802c0edd823147fa6acaebb2b", null ], + [ "mph_map", "namespacecrow_1_1multipart.html#a6a2722b508669592976047a34d6eba0c", null ], + [ "get_header_object", "namespacecrow_1_1multipart.html#acecc1d3d17777095c4439ce5159f035d", null ], + [ "get_header_value_object", "namespacecrow_1_1multipart.html#adb2a619f5ebb5d00a19d3e96dc3b0433", null ], + [ "dd", "namespacecrow_1_1multipart.html#a7abf735303db9e568bea5787e1a63b72", null ] +]; \ No newline at end of file diff --git a/1.2/reference/namespacecrow_1_1websocket.html b/1.2/reference/namespacecrow_1_1websocket.html new file mode 100644 index 000000000..1842fc870 --- /dev/null +++ b/1.2/reference/namespacecrow_1_1websocket.html @@ -0,0 +1,149 @@ + + + + + + + + Crow: crow::websocket Namespace Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::websocket Namespace Reference
+
+
+ +

Namespace that includes the Connection class and connection struct. Useful for WebSockets connection. +More...

+ + + + + + + + +

+Classes

struct  connection
 A base class for websocket connection. More...
 
class  Connection
 A websocket connection. More...
 
+ + + +

+Enumerations

enum class  WebSocketReadState {
+  MiniHeader +, Len16 +, Len64 +, Mask +,
+  Payload +
+ }
 
+

Detailed Description

+

Namespace that includes the Connection class and connection struct. Useful for WebSockets connection.

+

Used specially in crow/websocket.h, crow/app.h and crow/routing.h

+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/namespacecrow_1_1websocket.js b/1.2/reference/namespacecrow_1_1websocket.js new file mode 100644 index 000000000..1e230bc59 --- /dev/null +++ b/1.2/reference/namespacecrow_1_1websocket.js @@ -0,0 +1,12 @@ +var namespacecrow_1_1websocket = +[ + [ "connection", "structcrow_1_1websocket_1_1connection.html", "structcrow_1_1websocket_1_1connection" ], + [ "Connection", "classcrow_1_1websocket_1_1_connection.html", "classcrow_1_1websocket_1_1_connection" ], + [ "WebSocketReadState", "namespacecrow_1_1websocket.html#a2d7a65cf1c63efe21238c6e75c02334c", [ + [ "MiniHeader", "namespacecrow_1_1websocket.html#a2d7a65cf1c63efe21238c6e75c02334cad637a34702e8bfb6adc600f1ae827f35", null ], + [ "Len16", "namespacecrow_1_1websocket.html#a2d7a65cf1c63efe21238c6e75c02334ca6a687f78479d558a907bbaac0d7f53f0", null ], + [ "Len64", "namespacecrow_1_1websocket.html#a2d7a65cf1c63efe21238c6e75c02334cab70bcc4d8160e709624eaa6377a35c5d", null ], + [ "Mask", "namespacecrow_1_1websocket.html#a2d7a65cf1c63efe21238c6e75c02334ca4a18312b5b75f549d5551e5912ad6ebf", null ], + [ "Payload", "namespacecrow_1_1websocket.html#a2d7a65cf1c63efe21238c6e75c02334ca00f4e5788aab6d3546bb433842dbbefc", null ] + ] ] +]; \ No newline at end of file diff --git a/1.2/reference/namespacemembers.html b/1.2/reference/namespacemembers.html new file mode 100644 index 000000000..e4b981bcc --- /dev/null +++ b/1.2/reference/namespacemembers.html @@ -0,0 +1,135 @@ + + + + + + + + Crow: Namespace Members + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
Here is a list of all documented namespace members with links to the namespaces they belong to:
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/namespacemembers_func.html b/1.2/reference/namespacemembers_func.html new file mode 100644 index 000000000..f4ed95a04 --- /dev/null +++ b/1.2/reference/namespacemembers_func.html @@ -0,0 +1,123 @@ + + + + + + + + Crow: Namespace Members + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/namespacemembers_type.html b/1.2/reference/namespacemembers_type.html new file mode 100644 index 000000000..847e2e56a --- /dev/null +++ b/1.2/reference/namespacemembers_type.html @@ -0,0 +1,126 @@ + + + + + + + + Crow: Namespace Members + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/namespaces.html b/1.2/reference/namespaces.html new file mode 100644 index 000000000..8fba73107 --- /dev/null +++ b/1.2/reference/namespaces.html @@ -0,0 +1,228 @@ + + + + + + + + Crow: Namespace List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Namespace List
+
+
+
Here is a list of all documented namespaces with brief descriptions:
+
[detail level 12345]
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 NcrowThe main namespace of the library. In this namespace is defined the most important classes and functions of the library
 Ncompression
 Ndetail
 Nrouting_handler_call_helper
 Ccheck_before_handle_arity_3_const
 Ccheck_before_handle_arity_3
 Ccheck_after_handle_arity_3_const
 Ccheck_after_handle_arity_3
 Ccheck_global_call_false
 Cis_before_handle_arity_3_impl
 Cis_after_handle_arity_3_impl
 Cis_middleware_global
 Cmiddleware_call_criteria_only_global
 Cmiddleware_call_criteria_dynamic
 Cmiddleware_call_criteria_dynamic< false >
 Cmiddleware_call_criteria_dynamic< true >
 Cpartial_context
 Cpartial_context<>
 Ccontext
 Cmiddleware_indicesTypesafe wrapper for storing lists of middleware as their indices in the App
 Ctask_timerA class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 second
 Njson
 Ndetail
 CrvalueJSON read value
 CwvalueJSON write value
 Cwvalue_reader
 NmultipartEncapsulates anything related to processing and organizing multipart/xyz messages
 CheaderThe first part in a section, contains metadata about the part
 CpartOne part of the multipart message
 CmessageThe parsed multipart request/response
 Nmustache
 Ndetail
 Cinvalid_template_exception
 Crendered_template
 CAction
 Ctemplate_tA mustache template object
 Nsession
 Cmulti_value
 CExpirationTrackerExpiration tracker keeps track of soonest-to-expire keys
 CCachedSessionCachedSessions are shared across requests
 NwebsocketNamespace that includes the Connection class and connection struct. Useful for WebSockets connection
 CconnectionA base class for websocket connection
 CConnectionA websocket connection
 CCrowThe main server application class
 Cci_hashHashing function for ci_map (unordered_multimap)
 Cci_key_eqEquals function for ci_map (unordered_multimap)
 Crouting_handle_result
 CConnectionAn HTTP connection
 Chttp_parser
 Chttp_parser_settings
 CrequestAn HTTP request
 CresponseHTTP response
 Cstatic_file_infoThis constains metadata (coming from the stat command) related to any static files associated with this response
 CServer
 CILogHandler
 CCerrLogHandler
 Clogger
 CILocalMiddlewareLocal middleware should extend ILocalMiddleware
 CCookieParser
 Ccontext
 CCookie
 CCORSRulesUsed for tuning CORS policies
 CCORSHandlerCORSHandler is a global middleware for setting CORS headers
 Ccontext
 CSessionMiddleware
 Ccontext
 CInMemoryStoreInMemoryStore stores all entries in memory
 CFileStore
 CUTF8
 Ccontext
 CHTTPParserA wrapper for nodejs/http-parser
 Cquery_stringA class to represent any data coming after the ? in the request URL into key-value pairs
 CreturnableAn abstract class that allows any other class to be returned by a handler
 CBaseRuleA base class for all rules
 CCatchallRule
 CWebSocketRuleA rule dealing with websockets
 CRuleParameterTraitsAllows the user to assign parameters using functions
 CDynamicRuleA rule that can change its parameters during runtime
 CTaggedRuleDefault rule created when CROW_ROUTE is called
 CTrieA search tree
 CNode
 CBlueprintA blueprint can be considered a smaller section of a Crow app, specifically where the router is conecerned
 CRouterHandles matching requests to existing rules and upgrade requests
 CSocketAdaptorA wrapper for the asio::ip::tcp::socket and asio::ssl::stream
 CSSLAdaptor
 Nsha1Here is defined the SHA1 class
 CSHA1A tiny SHA1 algorithm implementation used internally in the Crow server (specifically in crow/websocket.h)
+
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/namespaces_dup.js b/1.2/reference/namespaces_dup.js new file mode 100644 index 000000000..a5bdfee1b --- /dev/null +++ b/1.2/reference/namespaces_dup.js @@ -0,0 +1,5 @@ +var namespaces_dup = +[ + [ "crow", "namespacecrow.html", "namespacecrow" ], + [ "sha1", "namespacesha1.html", "namespacesha1" ] +]; \ No newline at end of file diff --git a/1.2/reference/namespacesha1.html b/1.2/reference/namespacesha1.html new file mode 100644 index 000000000..3320dc53b --- /dev/null +++ b/1.2/reference/namespacesha1.html @@ -0,0 +1,131 @@ + + + + + + + + Crow: sha1 Namespace Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
sha1 Namespace Reference
+
+
+ +

Here is defined the SHA1 class. +More...

+ + + + + +

+Classes

class  SHA1
 A tiny SHA1 algorithm implementation used internally in the Crow server (specifically in crow/websocket.h). More...
 
+

Detailed Description

+

Here is defined the SHA1 class.

+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/namespacesha1.js b/1.2/reference/namespacesha1.js new file mode 100644 index 000000000..45ec91faa --- /dev/null +++ b/1.2/reference/namespacesha1.js @@ -0,0 +1,4 @@ +var namespacesha1 = +[ + [ "SHA1", "classsha1_1_1_s_h_a1.html", "classsha1_1_1_s_h_a1" ] +]; \ No newline at end of file diff --git a/1.2/reference/nav_f.png b/1.2/reference/nav_f.png new file mode 100644 index 000000000..72a58a529 Binary files /dev/null and b/1.2/reference/nav_f.png differ diff --git a/1.2/reference/nav_g.png b/1.2/reference/nav_g.png new file mode 100644 index 000000000..2093a237a Binary files /dev/null and b/1.2/reference/nav_g.png differ diff --git a/1.2/reference/nav_h.png b/1.2/reference/nav_h.png new file mode 100644 index 000000000..33389b101 Binary files /dev/null and b/1.2/reference/nav_h.png differ diff --git a/1.2/reference/navtree.css b/1.2/reference/navtree.css new file mode 100644 index 000000000..33341a67d --- /dev/null +++ b/1.2/reference/navtree.css @@ -0,0 +1,146 @@ +#nav-tree .children_ul { + margin:0; + padding:4px; +} + +#nav-tree ul { + list-style:none outside none; + margin:0px; + padding:0px; +} + +#nav-tree li { + white-space:nowrap; + margin:0px; + padding:0px; +} + +#nav-tree .plus { + margin:0px; +} + +#nav-tree .selected { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} + +#nav-tree img { + margin:0px; + padding:0px; + border:0px; + vertical-align: middle; +} + +#nav-tree a { + text-decoration:none; + padding:0px; + margin:0px; + outline:none; +} + +#nav-tree .label { + margin:0px; + padding:0px; + font: 12px 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +} + +#nav-tree .label a { + padding:2px; +} + +#nav-tree .selected a { + text-decoration:none; + color:#fff; +} + +#nav-tree .children_ul { + margin:0px; + padding:0px; +} + +#nav-tree .item { + margin:0px; + padding:0px; +} + +#nav-tree { + padding: 0px 0px; + background-color: #FAFAFF; + font-size:14px; + overflow:auto; +} + +#doc-content { + overflow:auto; + display:block; + padding:0px; + margin:0px; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +#side-nav { + padding:0 6px 0 0; + margin: 0px; + display:block; + position: absolute; + left: 0px; + width: 250px; +} + +.ui-resizable .ui-resizable-handle { + display:block; +} + +.ui-resizable-e { + background-image:url("splitbar.png"); + background-size:100%; + background-repeat:repeat-y; + background-attachment: scroll; + cursor:ew-resize; + height:100%; + right:0; + top:0; + width:6px; +} + +.ui-resizable-handle { + display:none; + font-size:0.1px; + position:absolute; + z-index:1; +} + +#nav-tree-contents { + margin: 6px 0px 0px 0px; +} + +#nav-tree { + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +#nav-sync { + position:absolute; + top:5px; + right:24px; + z-index:0; +} + +#nav-sync img { + opacity:0.3; +} + +#nav-sync img:hover { + opacity:0.9; +} + +@media print +{ + #nav-tree { display: none; } + div.ui-resizable-handle { display: none; position: relative; } +} + diff --git a/1.2/reference/navtree.js b/1.2/reference/navtree.js new file mode 100644 index 000000000..1e272d31d --- /dev/null +++ b/1.2/reference/navtree.js @@ -0,0 +1,546 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ +var navTreeSubIndices = new Array(); +var arrowDown = '▼'; +var arrowRight = '►'; + +function getData(varName) +{ + var i = varName.lastIndexOf('/'); + var n = i>=0 ? varName.substring(i+1) : varName; + return eval(n.replace(/\-/g,'_')); +} + +function stripPath(uri) +{ + return uri.substring(uri.lastIndexOf('/')+1); +} + +function stripPath2(uri) +{ + var i = uri.lastIndexOf('/'); + var s = uri.substring(i+1); + var m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/); + return m ? uri.substring(i-6) : s; +} + +function hashValue() +{ + return $(location).attr('hash').substring(1).replace(/[^\w\-]/g,''); +} + +function hashUrl() +{ + return '#'+hashValue(); +} + +function pathName() +{ + return $(location).attr('pathname').replace(/[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]/g, ''); +} + +function localStorageSupported() +{ + try { + return 'localStorage' in window && window['localStorage'] !== null && window.localStorage.getItem; + } + catch(e) { + return false; + } +} + +function storeLink(link) +{ + if (!$("#nav-sync").hasClass('sync') && localStorageSupported()) { + window.localStorage.setItem('navpath',link); + } +} + +function deleteLink() +{ + if (localStorageSupported()) { + window.localStorage.setItem('navpath',''); + } +} + +function cachedLink() +{ + if (localStorageSupported()) { + return window.localStorage.getItem('navpath'); + } else { + return ''; + } +} + +function getScript(scriptName,func,show) +{ + var head = document.getElementsByTagName("head")[0]; + var script = document.createElement('script'); + script.id = scriptName; + script.type = 'text/javascript'; + script.onload = func; + script.src = scriptName+'.js'; + head.appendChild(script); +} + +function createIndent(o,domNode,node,level) +{ + var level=-1; + var n = node; + while (n.parentNode) { level++; n=n.parentNode; } + if (node.childrenData) { + var imgNode = document.createElement("span"); + imgNode.className = 'arrow'; + imgNode.style.paddingLeft=(16*level).toString()+'px'; + imgNode.innerHTML=arrowRight; + node.plus_img = imgNode; + node.expandToggle = document.createElement("a"); + node.expandToggle.href = "javascript:void(0)"; + node.expandToggle.onclick = function() { + if (node.expanded) { + $(node.getChildrenUL()).slideUp("fast"); + node.plus_img.innerHTML=arrowRight; + node.expanded = false; + } else { + expandNode(o, node, false, false); + } + } + node.expandToggle.appendChild(imgNode); + domNode.appendChild(node.expandToggle); + } else { + var span = document.createElement("span"); + span.className = 'arrow'; + span.style.width = 16*(level+1)+'px'; + span.innerHTML = ' '; + domNode.appendChild(span); + } +} + +var animationInProgress = false; + +function gotoAnchor(anchor,aname,updateLocation) +{ + var pos, docContent = $('#doc-content'); + var ancParent = $(anchor.parent()); + if (ancParent.hasClass('memItemLeft') || + ancParent.hasClass('memtitle') || + ancParent.hasClass('fieldname') || + ancParent.hasClass('fieldtype') || + ancParent.is(':header')) + { + pos = ancParent.position().top; + } else if (anchor.position()) { + pos = anchor.position().top; + } + if (pos) { + var dist = Math.abs(Math.min( + pos-docContent.offset().top, + docContent[0].scrollHeight- + docContent.height()-docContent.scrollTop())); + animationInProgress=true; + docContent.animate({ + scrollTop: pos + docContent.scrollTop() - docContent.offset().top + },Math.max(50,Math.min(500,dist)),function(){ + if (updateLocation) window.location.href=aname; + animationInProgress=false; + }); + } +} + +function newNode(o, po, text, link, childrenData, lastNode) +{ + var node = new Object(); + node.children = Array(); + node.childrenData = childrenData; + node.depth = po.depth + 1; + node.relpath = po.relpath; + node.isLast = lastNode; + + node.li = document.createElement("li"); + po.getChildrenUL().appendChild(node.li); + node.parentNode = po; + + node.itemDiv = document.createElement("div"); + node.itemDiv.className = "item"; + + node.labelSpan = document.createElement("span"); + node.labelSpan.className = "label"; + + createIndent(o,node.itemDiv,node,0); + node.itemDiv.appendChild(node.labelSpan); + node.li.appendChild(node.itemDiv); + + var a = document.createElement("a"); + node.labelSpan.appendChild(a); + node.label = document.createTextNode(text); + node.expanded = false; + a.appendChild(node.label); + if (link) { + var url; + if (link.substring(0,1)=='^') { + url = link.substring(1); + link = url; + } else { + url = node.relpath+link; + } + a.className = stripPath(link.replace('#',':')); + if (link.indexOf('#')!=-1) { + var aname = '#'+link.split('#')[1]; + var srcPage = stripPath(pathName()); + var targetPage = stripPath(link.split('#')[0]); + a.href = srcPage!=targetPage ? url : "javascript:void(0)"; + a.onclick = function(){ + storeLink(link); + if (!$(a).parent().parent().hasClass('selected')) + { + $('.item').removeClass('selected'); + $('.item').removeAttr('id'); + $(a).parent().parent().addClass('selected'); + $(a).parent().parent().attr('id','selected'); + } + var anchor = $(aname); + gotoAnchor(anchor,aname,true); + }; + } else { + a.href = url; + a.onclick = function() { storeLink(link); } + } + } else { + if (childrenData != null) + { + a.className = "nolink"; + a.href = "javascript:void(0)"; + a.onclick = node.expandToggle.onclick; + } + } + + node.childrenUL = null; + node.getChildrenUL = function() { + if (!node.childrenUL) { + node.childrenUL = document.createElement("ul"); + node.childrenUL.className = "children_ul"; + node.childrenUL.style.display = "none"; + node.li.appendChild(node.childrenUL); + } + return node.childrenUL; + }; + + return node; +} + +function showRoot() +{ + var headerHeight = $("#top").height(); + var footerHeight = $("#nav-path").height(); + var windowHeight = $(window).height() - headerHeight - footerHeight; + (function (){ // retry until we can scroll to the selected item + try { + var navtree=$('#nav-tree'); + navtree.scrollTo('#selected',100,{offset:-windowHeight/2}); + } catch (err) { + setTimeout(arguments.callee, 0); + } + })(); +} + +function expandNode(o, node, imm, showRoot) +{ + if (node.childrenData && !node.expanded) { + if (typeof(node.childrenData)==='string') { + var varName = node.childrenData; + getScript(node.relpath+varName,function(){ + node.childrenData = getData(varName); + expandNode(o, node, imm, showRoot); + }, showRoot); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).slideDown("fast"); + node.plus_img.innerHTML = arrowDown; + node.expanded = true; + } + } +} + +function glowEffect(n,duration) +{ + n.addClass('glow').delay(duration).queue(function(next){ + $(this).removeClass('glow');next(); + }); +} + +function highlightAnchor() +{ + var aname = hashUrl(); + var anchor = $(aname); + if (anchor.parent().attr('class')=='memItemLeft'){ + var rows = $('.memberdecls tr[class$="'+hashValue()+'"]'); + glowEffect(rows.children(),300); // member without details + } else if (anchor.parent().attr('class')=='fieldname'){ + glowEffect(anchor.parent().parent(),1000); // enum value + } else if (anchor.parent().attr('class')=='fieldtype'){ + glowEffect(anchor.parent().parent(),1000); // struct field + } else if (anchor.parent().is(":header")) { + glowEffect(anchor.parent(),1000); // section header + } else { + glowEffect(anchor.next(),1000); // normal member + } +} + +function selectAndHighlight(hash,n) +{ + var a; + if (hash) { + var link=stripPath(pathName())+':'+hash.substring(1); + a=$('.item a[class$="'+link+'"]'); + } + if (a && a.length) { + a.parent().parent().addClass('selected'); + a.parent().parent().attr('id','selected'); + highlightAnchor(); + } else if (n) { + $(n.itemDiv).addClass('selected'); + $(n.itemDiv).attr('id','selected'); + } + if ($('#nav-tree-contents .item:first').hasClass('selected')) { + $('#nav-sync').css('top','30px'); + } else { + $('#nav-sync').css('top','5px'); + } + showRoot(); +} + +function showNode(o, node, index, hash) +{ + if (node && node.childrenData) { + if (typeof(node.childrenData)==='string') { + var varName = node.childrenData; + getScript(node.relpath+varName,function(){ + node.childrenData = getData(varName); + showNode(o,node,index,hash); + },true); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).css({'display':'block'}); + node.plus_img.innerHTML = arrowDown; + node.expanded = true; + var n = node.children[o.breadcrumbs[index]]; + if (index+11) hash = '#'+parts[1].replace(/[^\w\-]/g,''); + else hash=''; + } + if (hash.match(/^#l\d+$/)) { + var anchor=$('a[name='+hash.substring(1)+']'); + glowEffect(anchor.parent(),1000); // line number + hash=''; // strip line number anchors + } + var url=root+hash; + var i=-1; + while (NAVTREEINDEX[i+1]<=url) i++; + if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath) + } else { + getScript(relpath+'navtreeindex'+i,function(){ + navTreeSubIndices[i] = eval('NAVTREEINDEX'+i); + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath); + } + },true); + } +} + +function showSyncOff(n,relpath) +{ + n.html(''); +} + +function showSyncOn(n,relpath) +{ + n.html(''); +} + +function toggleSyncButton(relpath) +{ + var navSync = $('#nav-sync'); + if (navSync.hasClass('sync')) { + navSync.removeClass('sync'); + showSyncOff(navSync,relpath); + storeLink(stripPath2(pathName())+hashUrl()); + } else { + navSync.addClass('sync'); + showSyncOn(navSync,relpath); + deleteLink(); + } +} + +var loadTriggered = false; +var readyTriggered = false; +var loadObject,loadToRoot,loadUrl,loadRelPath; + +$(window).on('load',function(){ + if (readyTriggered) { // ready first + navTo(loadObject,loadToRoot,loadUrl,loadRelPath); + showRoot(); + } + loadTriggered=true; +}); + +function initNavTree(toroot,relpath) +{ + var o = new Object(); + o.toroot = toroot; + o.node = new Object(); + o.node.li = document.getElementById("nav-tree-contents"); + o.node.childrenData = NAVTREE; + o.node.children = new Array(); + o.node.childrenUL = document.createElement("ul"); + o.node.getChildrenUL = function() { return o.node.childrenUL; }; + o.node.li.appendChild(o.node.childrenUL); + o.node.depth = 0; + o.node.relpath = relpath; + o.node.expanded = false; + o.node.isLast = true; + o.node.plus_img = document.createElement("span"); + o.node.plus_img.className = 'arrow'; + o.node.plus_img.innerHTML = arrowRight; + + if (localStorageSupported()) { + var navSync = $('#nav-sync'); + if (cachedLink()) { + showSyncOff(navSync,relpath); + navSync.removeClass('sync'); + } else { + showSyncOn(navSync,relpath); + } + navSync.click(function(){ toggleSyncButton(relpath); }); + } + + if (loadTriggered) { // load before ready + navTo(o,toroot,hashUrl(),relpath); + showRoot(); + } else { // ready before load + loadObject = o; + loadToRoot = toroot; + loadUrl = hashUrl(); + loadRelPath = relpath; + readyTriggered=true; + } + + $(window).bind('hashchange', function(){ + if (window.location.hash && window.location.hash.length>1){ + var a; + if ($(location).attr('hash')){ + var clslink=stripPath(pathName())+':'+hashValue(); + a=$('.item a[class$="'+clslink.replace(/ + + + + + + + Crow: include/crow/parser.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
parser.h
+
+
+
1 #pragma once
+
2 
+
3 #include <string>
+
4 #include <unordered_map>
+
5 #include <algorithm>
+
6 
+
7 #include "crow/http_request.h"
+
8 #include "crow/http_parser_merged.h"
+
9 
+
10 namespace crow
+
11 {
+
12  /// A wrapper for `nodejs/http-parser`.
+
13 
+
14  ///
+
15  /// Used to generate a \ref crow.request from the TCP socket buffer.
+
16  template<typename Handler>
+
17  struct HTTPParser : public http_parser
+
18  {
+
19  static int on_message_begin(http_parser*)
+
20  {
+
21  return 0;
+
22  }
+
23  static int on_method(http_parser* self_)
+
24  {
+
25  HTTPParser* self = static_cast<HTTPParser*>(self_);
+
26  self->req.method = static_cast<HTTPMethod>(self->method);
+
27 
+
28  return 0;
+
29  }
+
30  static int on_url(http_parser* self_, const char* at, size_t length)
+
31  {
+
32  HTTPParser* self = static_cast<HTTPParser*>(self_);
+
33  self->req.raw_url.insert(self->req.raw_url.end(), at, at + length);
+
34  self->req.url_params = query_string(self->req.raw_url);
+
35  self->req.url = self->req.raw_url.substr(0, self->qs_point != 0 ? self->qs_point : std::string::npos);
+
36 
+
37  self->process_url();
+
38 
+
39  return 0;
+
40  }
+
41  static int on_header_field(http_parser* self_, const char* at, size_t length)
+
42  {
+
43  HTTPParser* self = static_cast<HTTPParser*>(self_);
+
44  switch (self->header_building_state)
+
45  {
+
46  case 0:
+
47  if (!self->header_value.empty())
+
48  {
+
49  self->req.headers.emplace(std::move(self->header_field), std::move(self->header_value));
+
50  }
+
51  self->header_field.assign(at, at + length);
+
52  self->header_building_state = 1;
+
53  break;
+
54  case 1:
+
55  self->header_field.insert(self->header_field.end(), at, at + length);
+
56  break;
+
57  }
+
58  return 0;
+
59  }
+
60  static int on_header_value(http_parser* self_, const char* at, size_t length)
+
61  {
+
62  HTTPParser* self = static_cast<HTTPParser*>(self_);
+
63  switch (self->header_building_state)
+
64  {
+
65  case 0:
+
66  self->header_value.insert(self->header_value.end(), at, at + length);
+
67  break;
+
68  case 1:
+
69  self->header_building_state = 0;
+
70  self->header_value.assign(at, at + length);
+
71  break;
+
72  }
+
73  return 0;
+
74  }
+
75  static int on_headers_complete(http_parser* self_)
+
76  {
+
77  HTTPParser* self = static_cast<HTTPParser*>(self_);
+
78  if (!self->header_field.empty())
+
79  {
+
80  self->req.headers.emplace(std::move(self->header_field), std::move(self->header_value));
+
81  }
+
82 
+
83  self->set_connection_parameters();
+
84 
+
85  self->process_header();
+
86  return 0;
+
87  }
+
88  static int on_body(http_parser* self_, const char* at, size_t length)
+
89  {
+
90  HTTPParser* self = static_cast<HTTPParser*>(self_);
+
91  self->req.body.insert(self->req.body.end(), at, at + length);
+
92  return 0;
+
93  }
+
94  static int on_message_complete(http_parser* self_)
+
95  {
+
96  HTTPParser* self = static_cast<HTTPParser*>(self_);
+
97 
+
98  self->message_complete = true;
+
99  self->process_message();
+
100  return 0;
+
101  }
+
102  HTTPParser(Handler* handler):
+
103  handler_(handler)
+
104  {
+
105  http_parser_init(this);
+
106  }
+
107 
+
108  // return false on error
+
109  /// Parse a buffer into the different sections of an HTTP request.
+
110  bool feed(const char* buffer, int length)
+
111  {
+
112  if (message_complete)
+
113  return true;
+
114 
+
115  const static http_parser_settings settings_{
+
116  on_message_begin,
+
117  on_method,
+
118  on_url,
+
119  on_header_field,
+
120  on_header_value,
+
121  on_headers_complete,
+
122  on_body,
+
123  on_message_complete,
+
124  };
+
125 
+
126  int nparsed = http_parser_execute(this, &settings_, buffer, length);
+
127  if (http_errno != CHPE_OK)
+
128  {
+
129  return false;
+
130  }
+
131  return nparsed == length;
+
132  }
+
133 
+
134  bool done()
+
135  {
+
136  return feed(nullptr, 0);
+
137  }
+
138 
+
139  void clear()
+
140  {
+
141  req = crow::request();
+
142  header_field.clear();
+
143  header_value.clear();
+
144  header_building_state = 0;
+
145  qs_point = 0;
+
146  message_complete = false;
+
147  state = CROW_NEW_MESSAGE();
+
148  }
+
149 
+
150  inline void process_url()
+
151  {
+
152  handler_->handle_url();
+
153  }
+
154 
+
155  inline void process_header()
+
156  {
+
157  handler_->handle_header();
+
158  }
+
159 
+
160  inline void process_message()
+
161  {
+
162  handler_->handle();
+
163  }
+
164 
+
165  inline void set_connection_parameters()
+
166  {
+
167  req.http_ver_major = http_major;
+
168  req.http_ver_minor = http_minor;
+
169 
+
170  //NOTE(EDev): it seems that the problem is with crow's policy on closing the connection for HTTP_VERSION < 1.0, the behaviour for that in crow is "don't close the connection, but don't send a keep-alive either"
+
171 
+
172  // HTTP1.1 = always send keep_alive, HTTP1.0 = only send if header exists, HTTP?.? = never send
+
173  req.keep_alive = (http_major == 1 && http_minor == 0) ?
+
174  ((flags & F_CONNECTION_KEEP_ALIVE) ? true : false) :
+
175  ((http_major == 1 && http_minor == 1) ? true : false);
+
176 
+
177  // HTTP1.1 = only close if close header exists, HTTP1.0 = always close unless keep_alive header exists, HTTP?.?= never close
+
178  req.close_connection = (http_major == 1 && http_minor == 0) ?
+
179  ((flags & F_CONNECTION_KEEP_ALIVE) ? false : true) :
+
180  ((http_major == 1 && http_minor == 1) ? ((flags & F_CONNECTION_CLOSE) ? true : false) : false);
+
181  req.upgrade = static_cast<bool>(upgrade);
+
182  }
+
183 
+
184  /// The final request that this parser outputs.
+
185  ///
+
186  /// Data parsed is put directly into this object as soon as the related callback returns. (e.g. the request will have the cooorect method as soon as on_method() returns)
+ +
188 
+
189  private:
+
190  int header_building_state = 0;
+
191  bool message_complete = false;
+
192  std::string header_field;
+
193  std::string header_value;
+
194 
+
195  Handler* handler_; ///< This is currently an HTTP connection object (\ref crow.Connection).
+
196  };
+
197 } // namespace crow
+
198 
+
199 #undef CROW_NEW_MESSAGE
+
200 #undef CROW_start_state
+
A class to represent any data coming after the ? in the request URL into key-value pairs.
Definition: query_string.h:294
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
A wrapper for nodejs/http-parser.
Definition: parser.h:18
+
request req
Definition: parser.h:187
+
bool feed(const char *buffer, int length)
Parse a buffer into the different sections of an HTTP request.
Definition: parser.h:110
+
Definition: http_parser_merged.h:181
+
Definition: http_parser_merged.h:148
+
unsigned char http_major
Definition: http_parser_merged.h:163
+
unsigned int flags
Definition: http_parser_merged.h:150
+
An HTTP request.
Definition: http_request.h:36
+
bool close_connection
Whether or not the server should shut down the TCP connection once a response is sent.
Definition: http_request.h:46
+
bool keep_alive
Whether or not the server should send a connection: Keep-Alive header to the client.
Definition: http_request.h:45
+
std::string raw_url
The full URL containing the ? and URL parameters.
Definition: http_request.h:38
+
bool upgrade
Whether or noth the server should change the HTTP connection to a different connection.
Definition: http_request.h:47
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/query__string_8h_source.html b/1.2/reference/query__string_8h_source.html new file mode 100644 index 000000000..4531a47e8 --- /dev/null +++ b/1.2/reference/query__string_8h_source.html @@ -0,0 +1,619 @@ + + + + + + + + Crow: include/crow/query_string.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
query_string.h
+
+
+
1 #pragma once
+
2 
+
3 #include <stdio.h>
+
4 #include <string.h>
+
5 #include <string>
+
6 #include <vector>
+
7 #include <unordered_map>
+
8 #include <iostream>
+
9 #include <memory>
+
10 
+
11 namespace crow
+
12 {
+
13 
+
14 // ----------------------------------------------------------------------------
+
15 // qs_parse (modified)
+
16 // https://github.com/bartgrantham/qs_parse
+
17 // ----------------------------------------------------------------------------
+
18 /* Similar to strncmp, but handles URL-encoding for either string */
+
19 int qs_strncmp(const char* s, const char* qs, size_t n);
+
20 
+
21 
+
22 /* Finds the beginning of each key/value pair and stores a pointer in qs_kv.
+
23  * Also decodes the value portion of the k/v pair *in-place*. In a future
+
24  * enhancement it will also have a compile-time option of sorting qs_kv
+
25  * alphabetically by key. */
+
26 size_t qs_parse(char* qs, char* qs_kv[], size_t qs_kv_size, bool parse_url);
+
27 
+
28 
+
29 /* Used by qs_parse to decode the value portion of a k/v pair */
+
30 int qs_decode(char * qs);
+
31 
+
32 
+
33 /* Looks up the value according to the key on a pre-processed query string
+
34  * A future enhancement will be a compile-time option to look up the key
+
35  * in a pre-sorted qs_kv array via a binary search. */
+
36 //char * qs_k2v(const char * key, char * qs_kv[], int qs_kv_size);
+
37  char * qs_k2v(const char * key, char * const * qs_kv, size_t qs_kv_size, int nth);
+
38 
+
39 
+
40 /* Non-destructive lookup of value, based on key. User provides the
+
41  * destinaton string and length. */
+
42 char * qs_scanvalue(const char * key, const char * qs, char * val, size_t val_len);
+
43 
+
44 // TODO: implement sorting of the qs_kv array; for now ensure it's not compiled
+
45 #undef _qsSORTING
+
46 
+
47 // isxdigit _is_ available in <ctype.h>, but let's avoid another header instead
+
48 #define CROW_QS_ISHEX(x) ((((x)>='0'&&(x)<='9') || ((x)>='A'&&(x)<='F') || ((x)>='a'&&(x)<='f')) ? 1 : 0)
+
49 #define CROW_QS_HEX2DEC(x) (((x)>='0'&&(x)<='9') ? (x)-48 : ((x)>='A'&&(x)<='F') ? (x)-55 : ((x)>='a'&&(x)<='f') ? (x)-87 : 0)
+
50 #define CROW_QS_ISQSCHR(x) ((((x)=='=')||((x)=='#')||((x)=='&')||((x)=='\0')) ? 0 : 1)
+
51 
+
52 inline int qs_strncmp(const char * s, const char * qs, size_t n)
+
53 {
+
54  unsigned char u1, u2, unyb, lnyb;
+
55 
+
56  while(n-- > 0)
+
57  {
+
58  u1 = static_cast<unsigned char>(*s++);
+
59  u2 = static_cast<unsigned char>(*qs++);
+
60 
+
61  if ( ! CROW_QS_ISQSCHR(u1) ) { u1 = '\0'; }
+
62  if ( ! CROW_QS_ISQSCHR(u2) ) { u2 = '\0'; }
+
63 
+
64  if ( u1 == '+' ) { u1 = ' '; }
+
65  if ( u1 == '%' ) // easier/safer than scanf
+
66  {
+
67  unyb = static_cast<unsigned char>(*s++);
+
68  lnyb = static_cast<unsigned char>(*s++);
+
69  if ( CROW_QS_ISHEX(unyb) && CROW_QS_ISHEX(lnyb) )
+
70  u1 = (CROW_QS_HEX2DEC(unyb) * 16) + CROW_QS_HEX2DEC(lnyb);
+
71  else
+
72  u1 = '\0';
+
73  }
+
74 
+
75  if ( u2 == '+' ) { u2 = ' '; }
+
76  if ( u2 == '%' ) // easier/safer than scanf
+
77  {
+
78  unyb = static_cast<unsigned char>(*qs++);
+
79  lnyb = static_cast<unsigned char>(*qs++);
+
80  if ( CROW_QS_ISHEX(unyb) && CROW_QS_ISHEX(lnyb) )
+
81  u2 = (CROW_QS_HEX2DEC(unyb) * 16) + CROW_QS_HEX2DEC(lnyb);
+
82  else
+
83  u2 = '\0';
+
84  }
+
85 
+
86  if ( u1 != u2 )
+
87  return u1 - u2;
+
88  if ( u1 == '\0' )
+
89  return 0;
+
90  }
+
91  if ( CROW_QS_ISQSCHR(*qs) )
+
92  return -1;
+
93  else
+
94  return 0;
+
95 }
+
96 
+
97 
+
98 inline size_t qs_parse(char* qs, char* qs_kv[], size_t qs_kv_size, bool parse_url = true)
+
99 {
+
100  size_t i, j;
+
101  char * substr_ptr;
+
102 
+
103  for(i=0; i<qs_kv_size; i++) qs_kv[i] = NULL;
+
104 
+
105  // find the beginning of the k/v substrings or the fragment
+
106  substr_ptr = parse_url ? qs + strcspn(qs, "?#") : qs;
+
107  if (parse_url)
+
108  {
+
109  if (substr_ptr[0] != '\0')
+
110  substr_ptr++;
+
111  else
+
112  return 0; // no query or fragment
+
113  }
+
114 
+
115  i=0;
+
116  while(i<qs_kv_size)
+
117  {
+
118  qs_kv[i] = substr_ptr;
+
119  j = strcspn(substr_ptr, "&");
+
120  if ( substr_ptr[j] == '\0' ) { i++; break; } // x &'s -> means x iterations of this loop -> means *x+1* k/v pairs
+
121  substr_ptr += j + 1;
+
122  i++;
+
123  }
+
124 
+
125  // we only decode the values in place, the keys could have '='s in them
+
126  // which will hose our ability to distinguish keys from values later
+
127  for(j=0; j<i; j++)
+
128  {
+
129  substr_ptr = qs_kv[j] + strcspn(qs_kv[j], "=&#");
+
130  if ( substr_ptr[0] == '&' || substr_ptr[0] == '\0') // blank value: skip decoding
+
131  substr_ptr[0] = '\0';
+
132  else
+
133  qs_decode(++substr_ptr);
+
134  }
+
135 
+
136 #ifdef _qsSORTING
+
137 // TODO: qsort qs_kv, using qs_strncmp() for the comparison
+
138 #endif
+
139 
+
140  return i;
+
141 }
+
142 
+
143 
+
144 inline int qs_decode(char * qs)
+
145 {
+
146  int i=0, j=0;
+
147 
+
148  while( CROW_QS_ISQSCHR(qs[j]) )
+
149  {
+
150  if ( qs[j] == '+' ) { qs[i] = ' '; }
+
151  else if ( qs[j] == '%' ) // easier/safer than scanf
+
152  {
+
153  if ( ! CROW_QS_ISHEX(qs[j+1]) || ! CROW_QS_ISHEX(qs[j+2]) )
+
154  {
+
155  qs[i] = '\0';
+
156  return i;
+
157  }
+
158  qs[i] = (CROW_QS_HEX2DEC(qs[j+1]) * 16) + CROW_QS_HEX2DEC(qs[j+2]);
+
159  j+=2;
+
160  }
+
161  else
+
162  {
+
163  qs[i] = qs[j];
+
164  }
+
165  i++; j++;
+
166  }
+
167  qs[i] = '\0';
+
168 
+
169  return i;
+
170 }
+
171 
+
172 
+
173 inline char * qs_k2v(const char * key, char * const * qs_kv, size_t qs_kv_size, int nth = 0)
+
174 {
+
175  size_t i;
+
176  size_t key_len, skip;
+
177 
+
178  key_len = strlen(key);
+
179 
+
180 #ifdef _qsSORTING
+
181 // TODO: binary search for key in the sorted qs_kv
+
182 #else // _qsSORTING
+
183  for(i=0; i<qs_kv_size; i++)
+
184  {
+
185  // we rely on the unambiguous '=' to find the value in our k/v pair
+
186  if ( qs_strncmp(key, qs_kv[i], key_len) == 0 )
+
187  {
+
188  skip = strcspn(qs_kv[i], "=");
+
189  if ( qs_kv[i][skip] == '=' )
+
190  skip++;
+
191  // return (zero-char value) ? ptr to trailing '\0' : ptr to value
+
192  if(nth == 0)
+
193  return qs_kv[i] + skip;
+
194  else
+
195  --nth;
+
196  }
+
197  }
+
198 #endif // _qsSORTING
+
199 
+
200  return nullptr;
+
201 }
+
202 
+
203 inline std::unique_ptr<std::pair<std::string, std::string>> qs_dict_name2kv(const char * dict_name, char * const * qs_kv, size_t qs_kv_size, int nth = 0)
+
204 {
+
205  size_t i;
+
206  size_t name_len, skip_to_eq, skip_to_brace_open, skip_to_brace_close;
+
207 
+
208  name_len = strlen(dict_name);
+
209 
+
210 #ifdef _qsSORTING
+
211 // TODO: binary search for key in the sorted qs_kv
+
212 #else // _qsSORTING
+
213  for(i=0; i<qs_kv_size; i++)
+
214  {
+
215  if ( strncmp(dict_name, qs_kv[i], name_len) == 0 )
+
216  {
+
217  skip_to_eq = strcspn(qs_kv[i], "=");
+
218  if ( qs_kv[i][skip_to_eq] == '=' )
+
219  skip_to_eq++;
+
220  skip_to_brace_open = strcspn(qs_kv[i], "[");
+
221  if ( qs_kv[i][skip_to_brace_open] == '[' )
+
222  skip_to_brace_open++;
+
223  skip_to_brace_close = strcspn(qs_kv[i], "]");
+
224 
+
225  if ( skip_to_brace_open <= skip_to_brace_close &&
+
226  skip_to_brace_open > 0 &&
+
227  skip_to_brace_close > 0 &&
+
228  nth == 0 )
+
229  {
+
230  auto key = std::string(qs_kv[i] + skip_to_brace_open, skip_to_brace_close - skip_to_brace_open);
+
231  auto value = std::string(qs_kv[i] + skip_to_eq);
+
232  return std::unique_ptr<std::pair<std::string, std::string>>(new std::pair<std::string, std::string>(key, value));
+
233  }
+
234  else
+
235  {
+
236  --nth;
+
237  }
+
238  }
+
239  }
+
240 #endif // _qsSORTING
+
241 
+
242  return nullptr;
+
243 }
+
244 
+
245 
+
246 inline char * qs_scanvalue(const char * key, const char * qs, char * val, size_t val_len)
+
247 {
+
248  size_t i, key_len;
+
249  const char * tmp;
+
250 
+
251  // find the beginning of the k/v substrings
+
252  if ( (tmp = strchr(qs, '?')) != NULL )
+
253  qs = tmp + 1;
+
254 
+
255  key_len = strlen(key);
+
256  while(qs[0] != '#' && qs[0] != '\0')
+
257  {
+
258  if ( qs_strncmp(key, qs, key_len) == 0 )
+
259  break;
+
260  qs += strcspn(qs, "&") + 1;
+
261  }
+
262 
+
263  if ( qs[0] == '\0' ) return NULL;
+
264 
+
265  qs += strcspn(qs, "=&#");
+
266  if ( qs[0] == '=' )
+
267  {
+
268  qs++;
+
269  i = strcspn(qs, "&=#");
+
270 #ifdef _MSC_VER
+
271  strncpy_s(val, val_len, qs, (val_len - 1)<(i + 1) ? (val_len - 1) : (i + 1));
+
272 #else
+
273  strncpy(val, qs, (val_len - 1)<(i + 1) ? (val_len - 1) : (i + 1));
+
274 #endif
+
275  qs_decode(val);
+
276  }
+
277  else
+
278  {
+
279  if ( val_len > 0 )
+
280  val[0] = '\0';
+
281  }
+
282 
+
283  return val;
+
284 }
+
285 }
+
286 // ----------------------------------------------------------------------------
+
287 
+
288 
+
289 namespace crow
+
290 {
+
291  struct request;
+
292  /// A class to represent any data coming after the `?` in the request URL into key-value pairs.
+ +
294  {
+
295  public:
+
296  static const int MAX_KEY_VALUE_PAIRS_COUNT = 256;
+
297 
+
298  query_string() = default;
+
299 
+
300  query_string(const query_string& qs):
+
301  url_(qs.url_)
+
302  {
+
303  for (auto p : qs.key_value_pairs_)
+
304  {
+
305  key_value_pairs_.push_back((char*)(p - qs.url_.c_str() + url_.c_str()));
+
306  }
+
307  }
+
308 
+
309  query_string& operator=(const query_string& qs)
+
310  {
+
311  url_ = qs.url_;
+
312  key_value_pairs_.clear();
+
313  for (auto p : qs.key_value_pairs_)
+
314  {
+
315  key_value_pairs_.push_back((char*)(p - qs.url_.c_str() + url_.c_str()));
+
316  }
+
317  return *this;
+
318  }
+
319 
+
320  query_string& operator=(query_string&& qs) noexcept
+
321  {
+
322  key_value_pairs_ = std::move(qs.key_value_pairs_);
+
323  char* old_data = (char*)qs.url_.c_str();
+
324  url_ = std::move(qs.url_);
+
325  for (auto& p : key_value_pairs_)
+
326  {
+
327  p += (char*)url_.c_str() - old_data;
+
328  }
+
329  return *this;
+
330  }
+
331 
+
332 
+
333  query_string(std::string params, bool url = true):
+
334  url_(std::move(params))
+
335  {
+
336  if (url_.empty())
+
337  return;
+
338 
+
339  key_value_pairs_.resize(MAX_KEY_VALUE_PAIRS_COUNT);
+
340  size_t count = qs_parse(&url_[0], &key_value_pairs_[0], MAX_KEY_VALUE_PAIRS_COUNT, url);
+
341 
+
342  key_value_pairs_.resize(count);
+
343  key_value_pairs_.shrink_to_fit();
+
344  }
+
345 
+
346  void clear()
+
347  {
+
348  key_value_pairs_.clear();
+
349  url_.clear();
+
350  }
+
351 
+
352  friend std::ostream& operator<<(std::ostream& os, const query_string& qs)
+
353  {
+
354  os << "[ ";
+
355  for (size_t i = 0; i < qs.key_value_pairs_.size(); ++i)
+
356  {
+
357  if (i)
+
358  os << ", ";
+
359  os << qs.key_value_pairs_[i];
+
360  }
+
361  os << " ]";
+
362  return os;
+
363  }
+
364 
+
365  /// Get a value from a name, used for `?name=value`.
+
366 
+
367  ///
+
368  /// Note: this method returns the value of the first occurrence of the key only, to return all occurrences, see \ref get_list().
+
369  char* get(const std::string& name) const
+
370  {
+
371  char* ret = qs_k2v(name.c_str(), key_value_pairs_.data(), key_value_pairs_.size());
+
372  return ret;
+
373  }
+
374 
+
375  /// Works similar to \ref get() except it removes the item from the query string.
+
376  char* pop(const std::string& name)
+
377  {
+
378  char* ret = get(name);
+
379  if (ret != nullptr)
+
380  {
+
381  for (unsigned int i = 0; i < key_value_pairs_.size(); i++)
+
382  {
+
383  std::string str_item(key_value_pairs_[i]);
+
384  if (str_item.substr(0, name.size() + 1) == name + '=')
+
385  {
+
386  key_value_pairs_.erase(key_value_pairs_.begin() + i);
+
387  break;
+
388  }
+
389  }
+
390  }
+
391  return ret;
+
392  }
+
393 
+
394  /// Returns a list of values, passed as `?name[]=value1&name[]=value2&...name[]=valuen` with n being the size of the list.
+
395 
+
396  ///
+
397  /// Note: Square brackets in the above example are controlled by `use_brackets` boolean (true by default). If set to false, the example becomes `?name=value1,name=value2...name=valuen`
+
398  std::vector<char*> get_list(const std::string& name, bool use_brackets = true) const
+
399  {
+
400  std::vector<char*> ret;
+
401  std::string plus = name + (use_brackets ? "[]" : "");
+
402  char* element = nullptr;
+
403 
+
404  int count = 0;
+
405  while (1)
+
406  {
+
407  element = qs_k2v(plus.c_str(), key_value_pairs_.data(), key_value_pairs_.size(), count++);
+
408  if (!element)
+
409  break;
+
410  ret.push_back(element);
+
411  }
+
412  return ret;
+
413  }
+
414 
+
415  /// Similar to \ref get_list() but it removes the
+
416  std::vector<char*> pop_list(const std::string& name, bool use_brackets = true)
+
417  {
+
418  std::vector<char*> ret = get_list(name, use_brackets);
+
419  if (!ret.empty())
+
420  {
+
421  for (unsigned int i = 0; i < key_value_pairs_.size(); i++)
+
422  {
+
423  std::string str_item(key_value_pairs_[i]);
+
424  if ((use_brackets ? (str_item.substr(0, name.size() + 3) == name + "[]=") : (str_item.substr(0, name.size() + 1) == name + '=')))
+
425  {
+
426  key_value_pairs_.erase(key_value_pairs_.begin() + i--);
+
427  }
+
428  }
+
429  }
+
430  return ret;
+
431  }
+
432 
+
433  /// Works similar to \ref get_list() except the brackets are mandatory must not be empty.
+
434 
+
435  ///
+
436  /// For example calling `get_dict(yourname)` on `?yourname[sub1]=42&yourname[sub2]=84` would give a map containing `{sub1 : 42, sub2 : 84}`.
+
437  ///
+
438  /// if your query string has both empty brackets and ones with a key inside, use pop_list() to get all the values without a key before running this method.
+
439  std::unordered_map<std::string, std::string> get_dict(const std::string& name) const
+
440  {
+
441  std::unordered_map<std::string, std::string> ret;
+
442 
+
443  int count = 0;
+
444  while (1)
+
445  {
+
446  if (auto element = qs_dict_name2kv(name.c_str(), key_value_pairs_.data(), key_value_pairs_.size(), count++))
+
447  ret.insert(*element);
+
448  else
+
449  break;
+
450  }
+
451  return ret;
+
452  }
+
453 
+
454  /// Works the same as \ref get_dict() but removes the values from the query string.
+
455  std::unordered_map<std::string, std::string> pop_dict(const std::string& name)
+
456  {
+
457  std::unordered_map<std::string, std::string> ret = get_dict(name);
+
458  if (!ret.empty())
+
459  {
+
460  for (unsigned int i = 0; i < key_value_pairs_.size(); i++)
+
461  {
+
462  std::string str_item(key_value_pairs_[i]);
+
463  if (str_item.substr(0, name.size() + 1) == name + '[')
+
464  {
+
465  key_value_pairs_.erase(key_value_pairs_.begin() + i--);
+
466  }
+
467  }
+
468  }
+
469  return ret;
+
470  }
+
471 
+
472  std::vector<std::string> keys() const
+
473  {
+
474  std::vector<std::string> keys;
+
475  keys.reserve(key_value_pairs_.size());
+
476 
+
477  for (const char* const element : key_value_pairs_)
+
478  {
+
479  const char* delimiter = strchr(element, '=');
+
480  if (delimiter)
+
481  keys.emplace_back(element, delimiter);
+
482  else
+
483  keys.emplace_back(element);
+
484  }
+
485 
+
486  return keys;
+
487  }
+
488 
+
489  private:
+
490  std::string url_;
+
491  std::vector<char*> key_value_pairs_;
+
492  };
+
493 
+
494 } // namespace crow
+
A class to represent any data coming after the ? in the request URL into key-value pairs.
Definition: query_string.h:294
+
std::unordered_map< std::string, std::string > pop_dict(const std::string &name)
Works the same as get_dict() but removes the values from the query string.
Definition: query_string.h:455
+
std::vector< char * > get_list(const std::string &name, bool use_brackets=true) const
Returns a list of values, passed as ?name[]=value1&name[]=value2&...name[]=valuen with n being the si...
Definition: query_string.h:398
+
char * get(const std::string &name) const
Get a value from a name, used for ?name=value.
Definition: query_string.h:369
+
std::vector< char * > pop_list(const std::string &name, bool use_brackets=true)
Similar to get_list() but it removes the.
Definition: query_string.h:416
+
char * pop(const std::string &name)
Works similar to get() except it removes the item from the query string.
Definition: query_string.h:376
+
std::unordered_map< std::string, std::string > get_dict(const std::string &name) const
Works similar to get_list() except the brackets are mandatory must not be empty.
Definition: query_string.h:439
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/resize.js b/1.2/reference/resize.js new file mode 100644 index 000000000..e1ad0fe3b --- /dev/null +++ b/1.2/reference/resize.js @@ -0,0 +1,140 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ +function initResizable() +{ + var cookie_namespace = 'doxygen'; + var sidenav,navtree,content,header,collapsed,collapsedWidth=0,barWidth=6,desktop_vp=768,titleHeight; + + function readCookie(cookie) + { + var myCookie = cookie_namespace+"_"+cookie+"="; + if (document.cookie) { + var index = document.cookie.indexOf(myCookie); + if (index != -1) { + var valStart = index + myCookie.length; + var valEnd = document.cookie.indexOf(";", valStart); + if (valEnd == -1) { + valEnd = document.cookie.length; + } + var val = document.cookie.substring(valStart, valEnd); + return val; + } + } + return 0; + } + + function writeCookie(cookie, val, expiration) + { + if (val==undefined) return; + if (expiration == null) { + var date = new Date(); + date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week + expiration = date.toGMTString(); + } + document.cookie = cookie_namespace + "_" + cookie + "=" + val + "; expires=" + expiration+"; path=/"; + } + + function resizeWidth() + { + var windowWidth = $(window).width() + "px"; + var sidenavWidth = $(sidenav).outerWidth(); + content.css({marginLeft:parseInt(sidenavWidth)+"px"}); + writeCookie('width',sidenavWidth-barWidth, null); + } + + function restoreWidth(navWidth) + { + var windowWidth = $(window).width() + "px"; + content.css({marginLeft:parseInt(navWidth)+barWidth+"px"}); + sidenav.css({width:navWidth + "px"}); + } + + function resizeHeight() + { + var headerHeight = header.outerHeight(); + var footerHeight = footer.outerHeight(); + var windowHeight = $(window).height() - headerHeight - footerHeight; + content.css({height:windowHeight + "px"}); + navtree.css({height:windowHeight + "px"}); + sidenav.css({height:windowHeight + "px"}); + var width=$(window).width(); + if (width!=collapsedWidth) { + if (width=desktop_vp) { + if (!collapsed) { + collapseExpand(); + } + } else if (width>desktop_vp && collapsedWidth0) { + restoreWidth(0); + collapsed=true; + } + else { + var width = readCookie('width'); + if (width>200 && width<$(window).width()) { restoreWidth(width); } else { restoreWidth(200); } + collapsed=false; + } + } + + header = $("#top"); + sidenav = $("#side-nav"); + content = $("#doc-content"); + navtree = $("#nav-tree"); + footer = $("#nav-path"); + $(".side-nav-resizable").resizable({resize: function(e, ui) { resizeWidth(); } }); + $(sidenav).resizable({ minWidth: 0 }); + $(window).resize(function() { resizeHeight(); }); + var device = navigator.userAgent.toLowerCase(); + var touch_device = device.match(/(iphone|ipod|ipad|android)/); + if (touch_device) { /* wider split bar for touch only devices */ + $(sidenav).css({ paddingRight:'20px' }); + $('.ui-resizable-e').css({ width:'20px' }); + $('#nav-sync').css({ right:'34px' }); + barWidth=20; + } + var width = readCookie('width'); + if (width) { restoreWidth(width); } else { resizeWidth(); } + resizeHeight(); + var url = location.href; + var i=url.indexOf("#"); + if (i>=0) window.location.hash=url.substr(i); + var _preventDefault = function(evt) { evt.preventDefault(); }; + $("#splitbar").bind("dragstart", _preventDefault).bind("selectstart", _preventDefault); + $(".ui-resizable-handle").dblclick(collapseExpand); + $(window).on('load',resizeHeight); +} +/* @license-end */ diff --git a/1.2/reference/returnable_8h_source.html b/1.2/reference/returnable_8h_source.html new file mode 100644 index 000000000..251f9b3af --- /dev/null +++ b/1.2/reference/returnable_8h_source.html @@ -0,0 +1,138 @@ + + + + + + + + Crow: include/crow/returnable.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
returnable.h
+
+
+
1 #pragma once
+
2 
+
3 #include <string>
+
4 
+
5 namespace crow
+
6 {
+
7  /// An abstract class that allows any other class to be returned by a handler.
+
8  struct returnable
+
9  {
+
10  std::string content_type;
+
11  virtual std::string dump() const = 0;
+
12 
+
13  returnable(std::string ctype):
+
14  content_type{ctype}
+
15  {}
+
16 
+
17  virtual ~returnable(){};
+
18  };
+
19 } // namespace crow
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
An abstract class that allows any other class to be returned by a handler.
Definition: returnable.h:9
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/routing_8h_source.html b/1.2/reference/routing_8h_source.html new file mode 100644 index 000000000..1753e5d68 --- /dev/null +++ b/1.2/reference/routing_8h_source.html @@ -0,0 +1,1982 @@ + + + + + + + + Crow: include/crow/routing.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
routing.h
+
+
+
1 #pragma once
+
2 
+
3 #include <cstdint>
+
4 #include <utility>
+
5 #include <tuple>
+
6 #include <unordered_map>
+
7 #include <memory>
+
8 #include <vector>
+
9 #include <algorithm>
+
10 #include <type_traits>
+
11 
+
12 #include "crow/common.h"
+
13 #include "crow/http_response.h"
+
14 #include "crow/http_request.h"
+
15 #include "crow/utility.h"
+
16 #include "crow/logging.h"
+
17 #include "crow/websocket.h"
+
18 #include "crow/mustache.h"
+
19 #include "crow/middleware.h"
+
20 
+
21 namespace crow // NOTE: Already documented in "crow/app.h"
+
22 {
+
23 
+
24  constexpr const uint16_t INVALID_BP_ID{((uint16_t)-1)};
+
25 
+
26  namespace detail
+
27  {
+
28  /// Typesafe wrapper for storing lists of middleware as their indices in the App
+ +
30  {
+
31  template<typename App>
+
32  void push()
+
33  {}
+
34 
+
35  template<typename App, typename MW, typename... Middlewares>
+
36  void push()
+
37  {
+
38  using MwContainer = typename App::mw_container_t;
+
39  static_assert(black_magic::has_type<MW, MwContainer>::value, "Middleware must be present in app");
+
40  static_assert(std::is_base_of<crow::ILocalMiddleware, MW>::value, "Middleware must extend ILocalMiddleware");
+
41  int idx = black_magic::tuple_index<MW, MwContainer>::value;
+
42  indices_.push_back(idx);
+
43  push<App, Middlewares...>();
+
44  }
+
45 
+
46  void merge_front(const detail::middleware_indices& other)
+
47  {
+
48  indices_.insert(indices_.begin(), other.indices_.cbegin(), other.indices_.cend());
+
49  }
+
50 
+
51  void merge_back(const detail::middleware_indices& other)
+
52  {
+
53  indices_.insert(indices_.end(), other.indices_.cbegin(), other.indices_.cend());
+
54  }
+
55 
+
56  void pop_back(const detail::middleware_indices& other)
+
57  {
+
58  indices_.resize(indices_.size() - other.indices_.size());
+
59  }
+
60 
+
61  bool empty() const
+
62  {
+
63  return indices_.empty();
+
64  }
+
65 
+
66  // Sorts indices and filters out duplicates to allow fast lookups with traversal
+
67  void pack()
+
68  {
+
69  std::sort(indices_.begin(), indices_.end());
+
70  indices_.erase(std::unique(indices_.begin(), indices_.end()), indices_.end());
+
71  }
+
72 
+
73  const std::vector<int>& indices()
+
74  {
+
75  return indices_;
+
76  }
+
77 
+
78  private:
+
79  std::vector<int> indices_;
+
80  };
+
81  } // namespace detail
+
82 
+
83  /// A base class for all rules.
+
84 
+
85  ///
+
86  /// Used to provide a common interface for code dealing with different types of rules.<br>
+
87  /// A Rule provides a URL, allowed HTTP methods, and handlers.
+
88  class BaseRule
+
89  {
+
90  public:
+
91  BaseRule(std::string rule):
+
92  rule_(std::move(rule))
+
93  {}
+
94 
+
95  virtual ~BaseRule()
+
96  {}
+
97 
+
98  virtual void validate() = 0;
+
99 
+
100  void set_added() {
+
101  added_ = true;
+
102  }
+
103 
+
104  bool is_added() {
+
105  return added_;
+
106  }
+
107 
+
108  std::unique_ptr<BaseRule> upgrade()
+
109  {
+
110  if (rule_to_upgrade_)
+
111  return std::move(rule_to_upgrade_);
+
112  return {};
+
113  }
+
114 
+
115  virtual void handle(request&, response&, const routing_params&) = 0;
+
116  virtual void handle_upgrade(const request&, response& res, SocketAdaptor&&)
+
117  {
+
118  res = response(404);
+
119  res.end();
+
120  }
+
121 #ifdef CROW_ENABLE_SSL
+
122  virtual void handle_upgrade(const request&, response& res, SSLAdaptor&&)
+
123  {
+
124  res = response(404);
+
125  res.end();
+
126  }
+
127 #endif
+
128 
+
129  uint32_t get_methods()
+
130  {
+
131  return methods_;
+
132  }
+
133 
+
134  template<typename F>
+
135  void foreach_method(F f)
+
136  {
+
137  for (uint32_t method = 0, method_bit = 1; method < static_cast<uint32_t>(HTTPMethod::InternalMethodCount); method++, method_bit <<= 1)
+
138  {
+
139  if (methods_ & method_bit)
+
140  f(method);
+
141  }
+
142  }
+
143 
+
144  std::string custom_templates_base;
+
145 
+
146  const std::string& rule() { return rule_; }
+
147 
+
148  protected:
+
149  uint32_t methods_{1 << static_cast<int>(HTTPMethod::Get)};
+
150 
+
151  std::string rule_;
+
152  std::string name_;
+
153  bool added_{false};
+
154 
+
155  std::unique_ptr<BaseRule> rule_to_upgrade_;
+
156 
+
157  detail::middleware_indices mw_indices_;
+
158 
+
159  friend class Router;
+
160  friend class Blueprint;
+
161  template<typename T>
+
162  friend struct RuleParameterTraits;
+
163  };
+
164 
+
165 
+
166  namespace detail
+
167  {
+
168  namespace routing_handler_call_helper
+
169  {
+
170  template<typename T, int Pos>
+
171  struct call_pair
+
172  {
+
173  using type = T;
+
174  static const int pos = Pos;
+
175  };
+
176 
+
177  template<typename H1>
+
178  struct call_params
+
179  {
+
180  H1& handler;
+
181  const routing_params& params;
+
182  request& req;
+
183  response& res;
+
184  };
+
185 
+
186  template<typename F, int NInt, int NUint, int NDouble, int NString, typename S1, typename S2>
+
187  struct call
+
188  {};
+
189 
+
190  template<typename F, int NInt, int NUint, int NDouble, int NString, typename... Args1, typename... Args2>
+
191  struct call<F, NInt, NUint, NDouble, NString, black_magic::S<int64_t, Args1...>, black_magic::S<Args2...>>
+
192  {
+
193  void operator()(F cparams)
+
194  {
+
195  using pushed = typename black_magic::S<Args2...>::template push_back<call_pair<int64_t, NInt>>;
+
196  call<F, NInt + 1, NUint, NDouble, NString, black_magic::S<Args1...>, pushed>()(cparams);
+
197  }
+
198  };
+
199 
+
200  template<typename F, int NInt, int NUint, int NDouble, int NString, typename... Args1, typename... Args2>
+
201  struct call<F, NInt, NUint, NDouble, NString, black_magic::S<uint64_t, Args1...>, black_magic::S<Args2...>>
+
202  {
+
203  void operator()(F cparams)
+
204  {
+
205  using pushed = typename black_magic::S<Args2...>::template push_back<call_pair<uint64_t, NUint>>;
+
206  call<F, NInt, NUint + 1, NDouble, NString, black_magic::S<Args1...>, pushed>()(cparams);
+
207  }
+
208  };
+
209 
+
210  template<typename F, int NInt, int NUint, int NDouble, int NString, typename... Args1, typename... Args2>
+
211  struct call<F, NInt, NUint, NDouble, NString, black_magic::S<double, Args1...>, black_magic::S<Args2...>>
+
212  {
+
213  void operator()(F cparams)
+
214  {
+
215  using pushed = typename black_magic::S<Args2...>::template push_back<call_pair<double, NDouble>>;
+
216  call<F, NInt, NUint, NDouble + 1, NString, black_magic::S<Args1...>, pushed>()(cparams);
+
217  }
+
218  };
+
219 
+
220  template<typename F, int NInt, int NUint, int NDouble, int NString, typename... Args1, typename... Args2>
+
221  struct call<F, NInt, NUint, NDouble, NString, black_magic::S<std::string, Args1...>, black_magic::S<Args2...>>
+
222  {
+
223  void operator()(F cparams)
+
224  {
+
225  using pushed = typename black_magic::S<Args2...>::template push_back<call_pair<std::string, NString>>;
+
226  call<F, NInt, NUint, NDouble, NString + 1, black_magic::S<Args1...>, pushed>()(cparams);
+
227  }
+
228  };
+
229 
+
230  template<typename F, int NInt, int NUint, int NDouble, int NString, typename... Args1>
+
231  struct call<F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S<Args1...>>
+
232  {
+
233  void operator()(F cparams)
+
234  {
+
235  cparams.handler(
+
236  cparams.req,
+
237  cparams.res,
+
238  cparams.params.template get<typename Args1::type>(Args1::pos)...);
+
239  }
+
240  };
+
241 
+
242  template<typename Func, typename... ArgsWrapped>
+
243  struct Wrapped
+
244  {
+
245  template<typename... Args>
+
246  void set_(Func f, typename std::enable_if<!std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value, int>::type = 0)
+
247  {
+
248  handler_ = (
+
249 #ifdef CROW_CAN_USE_CPP14
+
250  [f = std::move(f)]
+
251 #else
+
252  [f]
+
253 #endif
+
254  (const request&, response& res, Args... args) {
+
255  res = response(f(args...));
+
256  res.end();
+
257  });
+
258  }
+
259 
+
260  template<typename Req, typename... Args>
+ +
262  {
+
263  req_handler_wrapper(Func f):
+
264  f(std::move(f))
+
265  {
+
266  }
+
267 
+
268  void operator()(const request& req, response& res, Args... args)
+
269  {
+
270  res = response(f(req, args...));
+
271  res.end();
+
272  }
+
273 
+
274  Func f;
+
275  };
+
276 
+
277  template<typename... Args>
+
278  void set_(Func f, typename std::enable_if<
+
279  std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value &&
+
280  !std::is_same<typename std::tuple_element<1, std::tuple<Args..., void, void>>::type, response&>::value,
+
281  int>::type = 0)
+
282  {
+
283  handler_ = req_handler_wrapper<Args...>(std::move(f));
+
284  /*handler_ = (
+
285  [f = std::move(f)]
+
286  (const request& req, response& res, Args... args){
+
287  res = response(f(req, args...));
+
288  res.end();
+
289  });*/
+
290  }
+
291 
+
292  template<typename... Args>
+
293  void set_(Func f, typename std::enable_if<
+
294  std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value &&
+
295  std::is_same<typename std::tuple_element<1, std::tuple<Args..., void, void>>::type, response&>::value,
+
296  int>::type = 0)
+
297  {
+
298  handler_ = std::move(f);
+
299  }
+
300 
+
301  template<typename... Args>
+ +
303  {
+
304  using type = std::function<void(const crow::request&, crow::response&, Args...)>;
+
305  using args_type = black_magic::S<typename black_magic::promote_t<Args>...>;
+
306  };
+
307 
+
308  template<typename... Args>
+
309  struct handler_type_helper<const request&, Args...>
+
310  {
+
311  using type = std::function<void(const crow::request&, crow::response&, Args...)>;
+
312  using args_type = black_magic::S<typename black_magic::promote_t<Args>...>;
+
313  };
+
314 
+
315  template<typename... Args>
+
316  struct handler_type_helper<const request&, response&, Args...>
+
317  {
+
318  using type = std::function<void(const crow::request&, crow::response&, Args...)>;
+
319  using args_type = black_magic::S<typename black_magic::promote_t<Args>...>;
+
320  };
+
321 
+
322  typename handler_type_helper<ArgsWrapped...>::type handler_;
+
323 
+
324  void operator()(request& req, response& res, const routing_params& params)
+
325  {
+ + +
328  decltype(handler_)>,
+
329  0, 0, 0, 0,
+
330  typename handler_type_helper<ArgsWrapped...>::args_type,
+
331  black_magic::S<>>()(
+ +
333  decltype(handler_)>{handler_, params, req, res});
+
334  }
+
335  };
+
336 
+
337  } // namespace routing_handler_call_helper
+
338  } // namespace detail
+
339 
+
340 
+ +
342  {
+
343  public:
+
344  /// @cond SKIP
+
345  CatchallRule() {}
+
346 
+
347  template<typename Func>
+
348  typename std::enable_if<black_magic::CallHelper<Func, black_magic::S<>>::value, void>::type
+
349  operator()(Func&& f)
+
350  {
+
351  static_assert(!std::is_same<void, decltype(f())>::value,
+
352  "Handler function cannot have void return type; valid return types: string, int, crow::response, crow::returnable");
+
353 
+
354  handler_ = (
+
355 #ifdef CROW_CAN_USE_CPP14
+
356  [f = std::move(f)]
+
357 #else
+
358  [f]
+
359 #endif
+
360  (const request&, response& res) {
+
361  res = response(f());
+
362  res.end();
+
363  });
+
364  }
+
365 
+
366  template<typename Func>
+
367  typename std::enable_if<
+
368  !black_magic::CallHelper<Func, black_magic::S<>>::value &&
+
369  black_magic::CallHelper<Func, black_magic::S<crow::request>>::value,
+
370  void>::type
+
371  operator()(Func&& f)
+
372  {
+
373  static_assert(!std::is_same<void, decltype(f(std::declval<crow::request>()))>::value,
+
374  "Handler function cannot have void return type; valid return types: string, int, crow::response, crow::returnable");
+
375 
+
376  handler_ = (
+
377 #ifdef CROW_CAN_USE_CPP14
+
378  [f = std::move(f)]
+
379 #else
+
380  [f]
+
381 #endif
+
382  (const crow::request& req, crow::response& res) {
+
383  res = response(f(req));
+
384  res.end();
+
385  });
+
386  }
+
387 
+
388  template<typename Func>
+
389  typename std::enable_if<
+
390  !black_magic::CallHelper<Func, black_magic::S<>>::value &&
+
391  !black_magic::CallHelper<Func, black_magic::S<crow::request>>::value &&
+
392  black_magic::CallHelper<Func, black_magic::S<crow::response&>>::value,
+
393  void>::type
+
394  operator()(Func&& f)
+
395  {
+
396  static_assert(std::is_same<void, decltype(f(std::declval<crow::response&>()))>::value,
+
397  "Handler function with response argument should have void return type");
+
398  handler_ = (
+
399 #ifdef CROW_CAN_USE_CPP14
+
400  [f = std::move(f)]
+
401 #else
+
402  [f]
+
403 #endif
+
404  (const crow::request&, crow::response& res) {
+
405  f(res);
+
406  });
+
407  }
+
408 
+
409  template<typename Func>
+
410  typename std::enable_if<
+
411  !black_magic::CallHelper<Func, black_magic::S<>>::value &&
+
412  !black_magic::CallHelper<Func, black_magic::S<crow::request>>::value &&
+
413  !black_magic::CallHelper<Func, black_magic::S<crow::response&>>::value,
+
414  void>::type
+
415  operator()(Func&& f)
+
416  {
+
417  static_assert(std::is_same<void, decltype(f(std::declval<crow::request>(), std::declval<crow::response&>()))>::value,
+
418  "Handler function with response argument should have void return type");
+
419 
+
420  handler_ = std::move(f);
+
421  }
+
422  /// @endcond
+
423  bool has_handler()
+
424  {
+
425  return (handler_ != nullptr);
+
426  }
+
427 
+
428  protected:
+
429  friend class Router;
+
430 
+
431  private:
+
432  std::function<void(const crow::request&, crow::response&)> handler_;
+
433  };
+
434 
+
435 
+
436  /// A rule dealing with websockets.
+
437 
+
438  ///
+
439  /// Provides the interface for the user to put in the necessary handlers for a websocket to work.
+
440  template<typename App>
+
441  class WebSocketRule : public BaseRule
+
442  {
+
443  using self_t = WebSocketRule;
+
444 
+
445  public:
+
446  WebSocketRule(std::string rule, App* app):
+
447  BaseRule(std::move(rule)),
+
448  app_(app),
+
449  max_payload_(UINT64_MAX)
+
450  {}
+
451 
+
452  void validate() override
+
453  {}
+
454 
+
455  void handle(request&, response& res, const routing_params&) override
+
456  {
+
457  res = response(404);
+
458  res.end();
+
459  }
+
460 
+
461  void handle_upgrade(const request& req, response&, SocketAdaptor&& adaptor) override
+
462  {
+
463  max_payload_ = max_payload_override_ ? max_payload_ : app_->websocket_max_payload();
+
464  new crow::websocket::Connection<SocketAdaptor, App>(req, std::move(adaptor), app_, max_payload_, open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_);
+
465  }
+
466 #ifdef CROW_ENABLE_SSL
+
467  void handle_upgrade(const request& req, response&, SSLAdaptor&& adaptor) override
+
468  {
+
469  new crow::websocket::Connection<SSLAdaptor, App>(req, std::move(adaptor), app_, max_payload_, open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_);
+
470  }
+
471 #endif
+
472 
+
473  /// Override the global payload limit for this single WebSocket rule
+ +
475  {
+
476  max_payload_ = max_payload;
+
477  max_payload_override_ = true;
+
478  return *this;
+
479  }
+
480 
+
481  template<typename Func>
+
482  self_t& onopen(Func f)
+
483  {
+
484  open_handler_ = f;
+
485  return *this;
+
486  }
+
487 
+
488  template<typename Func>
+
489  self_t& onmessage(Func f)
+
490  {
+
491  message_handler_ = f;
+
492  return *this;
+
493  }
+
494 
+
495  template<typename Func>
+
496  self_t& onclose(Func f)
+
497  {
+
498  close_handler_ = f;
+
499  return *this;
+
500  }
+
501 
+
502  template<typename Func>
+
503  self_t& onerror(Func f)
+
504  {
+
505  error_handler_ = f;
+
506  return *this;
+
507  }
+
508 
+
509  template<typename Func>
+
510  self_t& onaccept(Func f)
+
511  {
+
512  accept_handler_ = f;
+
513  return *this;
+
514  }
+
515 
+
516  protected:
+
517  App* app_;
+
518  std::function<void(crow::websocket::connection&)> open_handler_;
+
519  std::function<void(crow::websocket::connection&, const std::string&, bool)> message_handler_;
+
520  std::function<void(crow::websocket::connection&, const std::string&)> close_handler_;
+
521  std::function<void(crow::websocket::connection&, const std::string&)> error_handler_;
+
522  std::function<bool(const crow::request&, void**)> accept_handler_;
+
523  uint64_t max_payload_;
+
524  bool max_payload_override_ = false;
+
525  };
+
526 
+
527  /// Allows the user to assign parameters using functions.
+
528 
+
529  ///
+
530  /// `rule.name("name").methods(HTTPMethod::POST)`
+
531  template<typename T>
+ +
533  {
+
534  using self_t = T;
+
535 
+
536  template<typename App>
+
537  WebSocketRule<App>& websocket(App* app)
+
538  {
+
539  auto p = new WebSocketRule<App>(static_cast<self_t*>(this)->rule_, app);
+
540  static_cast<self_t*>(this)->rule_to_upgrade_.reset(p);
+
541  return *p;
+
542  }
+
543 
+
544  self_t& name(std::string name) noexcept
+
545  {
+
546  static_cast<self_t*>(this)->name_ = std::move(name);
+
547  return static_cast<self_t&>(*this);
+
548  }
+
549 
+
550  self_t& methods(HTTPMethod method)
+
551  {
+
552  static_cast<self_t*>(this)->methods_ = 1 << static_cast<int>(method);
+
553  return static_cast<self_t&>(*this);
+
554  }
+
555 
+
556  template<typename... MethodArgs>
+
557  self_t& methods(HTTPMethod method, MethodArgs... args_method)
+
558  {
+
559  methods(args_method...);
+
560  static_cast<self_t*>(this)->methods_ |= 1 << static_cast<int>(method);
+
561  return static_cast<self_t&>(*this);
+
562  }
+
563 
+
564  /// Enable local middleware for this handler
+
565  template<typename App, typename... Middlewares>
+
566  self_t& middlewares()
+
567  {
+
568  static_cast<self_t*>(this)->mw_indices_.template push<App, Middlewares...>();
+
569  return static_cast<self_t&>(*this);
+
570  }
+
571  };
+
572 
+
573  /// A rule that can change its parameters during runtime.
+
574  class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule>
+
575  {
+
576  public:
+
577  DynamicRule(std::string rule):
+
578  BaseRule(std::move(rule))
+
579  {}
+
580 
+
581  void validate() override
+
582  {
+
583  if (!erased_handler_)
+
584  {
+
585  throw std::runtime_error(name_ + (!name_.empty() ? ": " : "") + "no handler for url " + rule_);
+
586  }
+
587  }
+
588 
+
589  void handle(request& req, response& res, const routing_params& params) override
+
590  {
+
591  if (!custom_templates_base.empty())
+
592  mustache::set_base(custom_templates_base);
+
593  else if (mustache::detail::get_template_base_directory_ref() != "templates")
+
594  mustache::set_base("templates");
+
595  erased_handler_(req, res, params);
+
596  }
+
597 
+
598  template<typename Func>
+
599  void operator()(Func f)
+
600  {
+
601 #ifdef CROW_MSVC_WORKAROUND
+
602  using function_t = utility::function_traits<decltype(&Func::operator())>;
+
603 #else
+
604  using function_t = utility::function_traits<Func>;
+
605 #endif
+
606  erased_handler_ = wrap(std::move(f), black_magic::gen_seq<function_t::arity>());
+
607  }
+
608 
+
609  // enable_if Arg1 == request && Arg2 == response
+
610  // enable_if Arg1 == request && Arg2 != resposne
+
611  // enable_if Arg1 != request
+
612 #ifdef CROW_MSVC_WORKAROUND
+
613  template<typename Func, size_t... Indices>
+
614 #else
+
615  template<typename Func, unsigned... Indices>
+
616 #endif
+
617  std::function<void(request&, response&, const routing_params&)>
+
618  wrap(Func f, black_magic::seq<Indices...>)
+
619  {
+
620 #ifdef CROW_MSVC_WORKAROUND
+
621  using function_t = utility::function_traits<decltype(&Func::operator())>;
+
622 #else
+
623  using function_t = utility::function_traits<Func>;
+
624 #endif
+
625  if (!black_magic::is_parameter_tag_compatible(
+
626  black_magic::get_parameter_tag_runtime(rule_.c_str()),
+
627  black_magic::compute_parameter_tag_from_args_list<
+
628  typename function_t::template arg<Indices>...>::value))
+
629  {
+
630  throw std::runtime_error("route_dynamic: Handler type is mismatched with URL parameters: " + rule_);
+
631  }
+ +
633  ret.template set_<
+
634  typename function_t::template arg<Indices>...>(std::move(f));
+
635  return ret;
+
636  }
+
637 
+
638  template<typename Func>
+
639  void operator()(std::string name, Func&& f)
+
640  {
+
641  name_ = std::move(name);
+
642  (*this).template operator()<Func>(std::forward(f));
+
643  }
+
644 
+
645  private:
+
646  std::function<void(request&, response&, const routing_params&)> erased_handler_;
+
647  };
+
648 
+
649  /// Default rule created when CROW_ROUTE is called.
+
650  template<typename... Args>
+
651  class TaggedRule : public BaseRule, public RuleParameterTraits<TaggedRule<Args...>>
+
652  {
+
653  public:
+
654  using self_t = TaggedRule<Args...>;
+
655 
+
656  TaggedRule(std::string rule):
+
657  BaseRule(std::move(rule))
+
658  {}
+
659 
+
660  void validate() override
+
661  {
+
662  if (rule_.at(0) != '/')
+
663  throw std::runtime_error("Internal error: Routes must start with a '/'");
+
664 
+
665  if (!handler_)
+
666  {
+
667  throw std::runtime_error(name_ + (!name_.empty() ? ": " : "") + "no handler for url " + rule_);
+
668  }
+
669  }
+
670 
+
671  template<typename Func>
+
672  void operator()(Func&& f)
+
673  {
+
674  handler_ = (
+
675 #ifdef CROW_CAN_USE_CPP14
+
676  [f = std::move(f)]
+
677 #else
+
678  [f]
+
679 #endif
+
680  (crow::request& req, crow::response& res, Args... args) {
+
681  detail::wrapped_handler_call(req, res, f, std::forward<Args>(args)...);
+
682  });
+
683  }
+
684 
+
685  template<typename Func>
+
686  void operator()(std::string name, Func&& f)
+
687  {
+
688  name_ = std::move(name);
+
689  (*this).template operator()<Func>(std::forward(f));
+
690  }
+
691 
+
692  void handle(request& req, response& res, const routing_params& params) override
+
693  {
+
694  if (!custom_templates_base.empty())
+
695  mustache::set_base(custom_templates_base);
+
696  else if (mustache::detail::get_template_base_directory_ref() != mustache::detail::get_global_template_base_directory_ref())
+
697  mustache::set_base(mustache::detail::get_global_template_base_directory_ref());
+
698 
+ + +
701  0, 0, 0, 0,
+
702  black_magic::S<Args...>,
+
703  black_magic::S<>>()(
+
704  detail::routing_handler_call_helper::call_params<decltype(handler_)>{handler_, params, req, res});
+
705  }
+
706 
+
707  private:
+
708  std::function<void(crow::request&, crow::response&, Args...)> handler_;
+
709  };
+
710 
+
711  const int RULE_SPECIAL_REDIRECT_SLASH = 1;
+
712 
+
713 
+
714  /// A search tree.
+
715  class Trie
+
716  {
+
717  public:
+
718  struct Node
+
719  {
+
720  uint16_t rule_index{};
+
721  // Assign the index to the maximum 32 unsigned integer value by default so that any other number (specifically 0) is a valid BP id.
+
722  uint16_t blueprint_index{INVALID_BP_ID};
+
723  std::string key;
+
724  ParamType param = ParamType::MAX; // MAX = No param.
+
725  std::vector<Node> children;
+
726 
+
727  bool IsSimpleNode() const
+
728  {
+
729  return !rule_index &&
+
730  blueprint_index == INVALID_BP_ID &&
+
731  children.size() < 2 &&
+
732  param == ParamType::MAX &&
+
733  std::all_of(std::begin(children), std::end(children), [](const Node& x) {
+
734  return x.param == ParamType::MAX;
+
735  });
+
736  }
+
737 
+
738  Node& add_child_node()
+
739  {
+
740  children.emplace_back();
+
741  return children.back();
+
742  }
+
743  };
+
744 
+
745 
+
746  Trie()
+
747  {}
+
748 
+
749  /// Check whether or not the trie is empty.
+
750  bool is_empty()
+
751  {
+
752  return head_.children.empty();
+
753  }
+
754 
+
755  void optimize()
+
756  {
+
757  for (auto& child : head_.children)
+
758  {
+
759  optimizeNode(child);
+
760  }
+
761  }
+
762 
+
763 
+
764  private:
+
765  void optimizeNode(Node& node)
+
766  {
+
767  if (node.children.empty())
+
768  return;
+
769  if (node.IsSimpleNode())
+
770  {
+
771  auto children_temp = std::move(node.children);
+
772  auto& child_temp = children_temp[0];
+
773  node.key += child_temp.key;
+
774  node.rule_index = child_temp.rule_index;
+
775  node.blueprint_index = child_temp.blueprint_index;
+
776  node.children = std::move(child_temp.children);
+
777  optimizeNode(node);
+
778  }
+
779  else
+
780  {
+
781  for (auto& child : node.children)
+
782  {
+
783  optimizeNode(child);
+
784  }
+
785  }
+
786  }
+
787 
+
788  void debug_node_print(const Node& node, int level)
+
789  {
+
790  if (node.param != ParamType::MAX)
+
791  {
+
792  switch (node.param)
+
793  {
+
794  case ParamType::INT:
+
795  CROW_LOG_DEBUG << std::string(3 * level, ' ') << "└➝ "
+
796  << "<int>";
+
797  break;
+
798  case ParamType::UINT:
+
799  CROW_LOG_DEBUG << std::string(3 * level, ' ') << "└➝ "
+
800  << "<uint>";
+
801  break;
+
802  case ParamType::DOUBLE:
+
803  CROW_LOG_DEBUG << std::string(3 * level, ' ') << "└➝ "
+
804  << "<double>";
+
805  break;
+
806  case ParamType::STRING:
+
807  CROW_LOG_DEBUG << std::string(3 * level, ' ') << "└➝ "
+
808  << "<string>";
+
809  break;
+
810  case ParamType::PATH:
+
811  CROW_LOG_DEBUG << std::string(3 * level, ' ') << "└➝ "
+
812  << "<path>";
+
813  break;
+
814  default:
+
815  CROW_LOG_DEBUG << std::string(3 * level, ' ') << "└➝ "
+
816  << "<ERROR>";
+
817  break;
+
818  }
+
819  }
+
820  else
+
821  CROW_LOG_DEBUG << std::string(3 * level, ' ') << "└➝ " << node.key;
+
822 
+
823  for (const auto& child : node.children)
+
824  {
+
825  debug_node_print(child, level + 1);
+
826  }
+
827  }
+
828 
+
829  public:
+
830  void debug_print()
+
831  {
+
832  CROW_LOG_DEBUG << "└➙ ROOT";
+
833  for (const auto& child : head_.children)
+
834  debug_node_print(child, 1);
+
835  }
+
836 
+
837  void validate()
+
838  {
+
839  if (!head_.IsSimpleNode())
+
840  throw std::runtime_error("Internal error: Trie header should be simple!");
+
841  optimize();
+
842  }
+
843 
+
844  //Rule_index, Blueprint_index, routing_params
+
845  routing_handle_result find(const std::string& req_url, const Node& node, unsigned pos = 0, routing_params* params = nullptr, std::vector<uint16_t>* blueprints = nullptr) const
+
846  {
+
847  //start params as an empty struct
+
848  routing_params empty;
+
849  if (params == nullptr)
+
850  params = &empty;
+
851  //same for blueprint vector
+
852  std::vector<uint16_t> MT;
+
853  if (blueprints == nullptr)
+
854  blueprints = &MT;
+
855 
+
856  uint16_t found{}; //The rule index to be found
+
857  std::vector<uint16_t> found_BP; //The Blueprint indices to be found
+
858  routing_params match_params; //supposedly the final matched parameters
+
859 
+
860  auto update_found = [&found, &found_BP, &match_params](routing_handle_result& ret) {
+
861  found_BP = std::move(ret.blueprint_indices);
+
862  if (ret.rule_index && (!found || found > ret.rule_index))
+
863  {
+
864  found = ret.rule_index;
+
865  match_params = std::move(ret.r_params);
+
866  }
+
867  };
+
868 
+
869  //if the function was called on a node at the end of the string (the last recursion), return the nodes rule index, and whatever params were passed to the function
+
870  if (pos == req_url.size())
+
871  {
+
872  found_BP = std::move(*blueprints);
+
873  return routing_handle_result{node.rule_index, *blueprints, *params};
+
874  }
+
875 
+
876  bool found_fragment = false;
+
877 
+
878  for (const auto& child : node.children)
+
879  {
+
880  if (child.param != ParamType::MAX)
+
881  {
+
882  if (child.param == ParamType::INT)
+
883  {
+
884  char c = req_url[pos];
+
885  if ((c >= '0' && c <= '9') || c == '+' || c == '-')
+
886  {
+
887  char* eptr;
+
888  errno = 0;
+
889  long long int value = strtoll(req_url.data() + pos, &eptr, 10);
+
890  if (errno != ERANGE && eptr != req_url.data() + pos)
+
891  {
+
892  found_fragment = true;
+
893  params->int_params.push_back(value);
+
894  if (child.blueprint_index != INVALID_BP_ID) blueprints->push_back(child.blueprint_index);
+
895  auto ret = find(req_url, child, eptr - req_url.data(), params, blueprints);
+
896  update_found(ret);
+
897  params->int_params.pop_back();
+
898  if (!blueprints->empty()) blueprints->pop_back();
+
899  }
+
900  }
+
901  }
+
902 
+
903  else if (child.param == ParamType::UINT)
+
904  {
+
905  char c = req_url[pos];
+
906  if ((c >= '0' && c <= '9') || c == '+')
+
907  {
+
908  char* eptr;
+
909  errno = 0;
+
910  unsigned long long int value = strtoull(req_url.data() + pos, &eptr, 10);
+
911  if (errno != ERANGE && eptr != req_url.data() + pos)
+
912  {
+
913  found_fragment = true;
+
914  params->uint_params.push_back(value);
+
915  if (child.blueprint_index != INVALID_BP_ID) blueprints->push_back(child.blueprint_index);
+
916  auto ret = find(req_url, child, eptr - req_url.data(), params, blueprints);
+
917  update_found(ret);
+
918  params->uint_params.pop_back();
+
919  if (!blueprints->empty()) blueprints->pop_back();
+
920  }
+
921  }
+
922  }
+
923 
+
924  else if (child.param == ParamType::DOUBLE)
+
925  {
+
926  char c = req_url[pos];
+
927  if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')
+
928  {
+
929  char* eptr;
+
930  errno = 0;
+
931  double value = strtod(req_url.data() + pos, &eptr);
+
932  if (errno != ERANGE && eptr != req_url.data() + pos)
+
933  {
+
934  found_fragment = true;
+
935  params->double_params.push_back(value);
+
936  if (child.blueprint_index != INVALID_BP_ID) blueprints->push_back(child.blueprint_index);
+
937  auto ret = find(req_url, child, eptr - req_url.data(), params, blueprints);
+
938  update_found(ret);
+
939  params->double_params.pop_back();
+
940  if (!blueprints->empty()) blueprints->pop_back();
+
941  }
+
942  }
+
943  }
+
944 
+
945  else if (child.param == ParamType::STRING)
+
946  {
+
947  size_t epos = pos;
+
948  for (; epos < req_url.size(); epos++)
+
949  {
+
950  if (req_url[epos] == '/')
+
951  break;
+
952  }
+
953 
+
954  if (epos != pos)
+
955  {
+
956  found_fragment = true;
+
957  params->string_params.push_back(req_url.substr(pos, epos - pos));
+
958  if (child.blueprint_index != INVALID_BP_ID) blueprints->push_back(child.blueprint_index);
+
959  auto ret = find(req_url, child, epos, params, blueprints);
+
960  update_found(ret);
+
961  params->string_params.pop_back();
+
962  if (!blueprints->empty()) blueprints->pop_back();
+
963  }
+
964  }
+
965 
+
966  else if (child.param == ParamType::PATH)
+
967  {
+
968  size_t epos = req_url.size();
+
969 
+
970  if (epos != pos)
+
971  {
+
972  found_fragment = true;
+
973  params->string_params.push_back(req_url.substr(pos, epos - pos));
+
974  if (child.blueprint_index != INVALID_BP_ID) blueprints->push_back(child.blueprint_index);
+
975  auto ret = find(req_url, child, epos, params, blueprints);
+
976  update_found(ret);
+
977  params->string_params.pop_back();
+
978  if (!blueprints->empty()) blueprints->pop_back();
+
979  }
+
980  }
+
981  }
+
982 
+
983  else
+
984  {
+
985  const std::string& fragment = child.key;
+
986  if (req_url.compare(pos, fragment.size(), fragment) == 0)
+
987  {
+
988  found_fragment = true;
+
989  if (child.blueprint_index != INVALID_BP_ID) blueprints->push_back(child.blueprint_index);
+
990  auto ret = find(req_url, child, pos + fragment.size(), params, blueprints);
+
991  update_found(ret);
+
992  if (!blueprints->empty()) blueprints->pop_back();
+
993  }
+
994  }
+
995  }
+
996 
+
997  if (!found_fragment)
+
998  found_BP = std::move(*blueprints);
+
999 
+
1000  return routing_handle_result{found, found_BP, match_params}; //Called after all the recursions have been done
+
1001  }
+
1002 
+
1003  routing_handle_result find(const std::string& req_url) const
+
1004  {
+
1005  return find(req_url, head_);
+
1006  }
+
1007 
+
1008  //This functions assumes any blueprint info passed is valid
+
1009  void add(const std::string& url, uint16_t rule_index, unsigned bp_prefix_length = 0, uint16_t blueprint_index = INVALID_BP_ID)
+
1010  {
+
1011  auto idx = &head_;
+
1012 
+
1013  bool has_blueprint = bp_prefix_length != 0 && blueprint_index != INVALID_BP_ID;
+
1014 
+
1015  for (unsigned i = 0; i < url.size(); i++)
+
1016  {
+
1017  char c = url[i];
+
1018  if (c == '<')
+
1019  {
+
1020  static struct ParamTraits
+
1021  {
+
1022  ParamType type;
+
1023  std::string name;
+
1024  } paramTraits[] =
+
1025  {
+
1026  {ParamType::INT, "<int>"},
+
1027  {ParamType::UINT, "<uint>"},
+
1028  {ParamType::DOUBLE, "<float>"},
+
1029  {ParamType::DOUBLE, "<double>"},
+
1030  {ParamType::STRING, "<str>"},
+
1031  {ParamType::STRING, "<string>"},
+
1032  {ParamType::PATH, "<path>"},
+
1033  };
+
1034 
+
1035  for (const auto& x : paramTraits)
+
1036  {
+
1037  if (url.compare(i, x.name.size(), x.name) == 0)
+
1038  {
+
1039  bool found = false;
+
1040  for (auto& child : idx->children)
+
1041  {
+
1042  if (child.param == x.type)
+
1043  {
+
1044  idx = &child;
+
1045  i += x.name.size();
+
1046  found = true;
+
1047  break;
+
1048  }
+
1049  }
+
1050  if (found)
+
1051  break;
+
1052 
+
1053  auto new_node_idx = &idx->add_child_node();
+
1054  new_node_idx->param = x.type;
+
1055  idx = new_node_idx;
+
1056  i += x.name.size();
+
1057  break;
+
1058  }
+
1059  }
+
1060 
+
1061  i--;
+
1062  }
+
1063  else
+
1064  {
+
1065  //This part assumes the tree is unoptimized (every node has a max 1 character key)
+
1066  bool piece_found = false;
+
1067  for (auto& child : idx->children)
+
1068  {
+
1069  if (child.key[0] == c)
+
1070  {
+
1071  idx = &child;
+
1072  piece_found = true;
+
1073  break;
+
1074  }
+
1075  }
+
1076  if (!piece_found)
+
1077  {
+
1078  auto new_node_idx = &idx->add_child_node();
+
1079  new_node_idx->key = c;
+
1080  //The assumption here is that you'd only need to add a blueprint index if the tree didn't have the BP prefix.
+
1081  if (has_blueprint && i == bp_prefix_length)
+
1082  new_node_idx->blueprint_index = blueprint_index;
+
1083  idx = new_node_idx;
+
1084  }
+
1085  }
+
1086  }
+
1087 
+
1088  //check if the last node already has a value (exact url already in Trie)
+
1089  if (idx->rule_index)
+
1090  throw std::runtime_error("handler already exists for " + url);
+
1091  idx->rule_index = rule_index;
+
1092  }
+
1093 
+
1094  private:
+
1095  Node head_;
+
1096  };
+
1097 
+
1098  /// A blueprint can be considered a smaller section of a Crow app, specifically where the router is conecerned.
+
1099 
+
1100  ///
+
1101  /// You can use blueprints to assign a common prefix to rules' prefix, set custom static and template folders, and set a custom catchall route.
+
1102  /// You can also assign nest blueprints for maximum Compartmentalization.
+ +
1104  {
+
1105  public:
+
1106  Blueprint(const std::string& prefix):
+
1107  prefix_(prefix){};
+
1108 
+
1109  Blueprint(const std::string& prefix, const std::string& static_dir):
+
1110  prefix_(prefix), static_dir_(static_dir){};
+
1111 
+
1112  Blueprint(const std::string& prefix, const std::string& static_dir, const std::string& templates_dir):
+
1113  prefix_(prefix), static_dir_(static_dir), templates_dir_(templates_dir){};
+
1114 
+
1115  /*
+
1116  Blueprint(Blueprint& other)
+
1117  {
+
1118  prefix_ = std::move(other.prefix_);
+
1119  all_rules_ = std::move(other.all_rules_);
+
1120  }
+
1121 
+
1122  Blueprint(const Blueprint& other)
+
1123  {
+
1124  prefix_ = other.prefix_;
+
1125  all_rules_ = other.all_rules_;
+
1126  }
+
1127 */
+
1128  Blueprint(Blueprint&& value)
+
1129  {
+
1130  *this = std::move(value);
+
1131  }
+
1132 
+
1133  Blueprint& operator=(const Blueprint& value) = delete;
+
1134 
+
1135  Blueprint& operator=(Blueprint&& value) noexcept
+
1136  {
+
1137  prefix_ = std::move(value.prefix_);
+
1138  static_dir_ = std::move(value.static_dir_);
+
1139  templates_dir_ = std::move(value.templates_dir_);
+
1140  all_rules_ = std::move(value.all_rules_);
+
1141  catchall_rule_ = std::move(value.catchall_rule_);
+
1142  blueprints_ = std::move(value.blueprints_);
+
1143  mw_indices_ = std::move(value.mw_indices_);
+
1144  return *this;
+
1145  }
+
1146 
+
1147  bool operator==(const Blueprint& value)
+
1148  {
+
1149  return value.prefix() == prefix_;
+
1150  }
+
1151 
+
1152  bool operator!=(const Blueprint& value)
+
1153  {
+
1154  return value.prefix() != prefix_;
+
1155  }
+
1156 
+
1157  std::string prefix() const
+
1158  {
+
1159  return prefix_;
+
1160  }
+
1161 
+
1162  std::string static_dir() const
+
1163  {
+
1164  return static_dir_;
+
1165  }
+
1166 
+
1167  void set_added() {
+
1168  added_ = true;
+
1169  }
+
1170 
+
1171  bool is_added() {
+
1172  return added_;
+
1173  }
+
1174 
+
1175  DynamicRule& new_rule_dynamic(const std::string& rule)
+
1176  {
+
1177  std::string new_rule = '/' + prefix_ + rule;
+
1178  auto ruleObject = new DynamicRule(std::move(new_rule));
+
1179  ruleObject->custom_templates_base = templates_dir_;
+
1180  all_rules_.emplace_back(ruleObject);
+
1181 
+
1182  return *ruleObject;
+
1183  }
+
1184 
+
1185  template<uint64_t N>
+
1186  typename black_magic::arguments<N>::type::template rebind<TaggedRule>& new_rule_tagged(const std::string& rule)
+
1187  {
+
1188  std::string new_rule = '/' + prefix_ + rule;
+
1189  using RuleT = typename black_magic::arguments<N>::type::template rebind<TaggedRule>;
+
1190 
+
1191  auto ruleObject = new RuleT(std::move(new_rule));
+
1192  ruleObject->custom_templates_base = templates_dir_;
+
1193  all_rules_.emplace_back(ruleObject);
+
1194 
+
1195  return *ruleObject;
+
1196  }
+
1197 
+
1198  void register_blueprint(Blueprint& blueprint)
+
1199  {
+
1200  if (blueprints_.empty() || std::find(blueprints_.begin(), blueprints_.end(), &blueprint) == blueprints_.end())
+
1201  {
+
1202  apply_blueprint(blueprint);
+
1203  blueprints_.emplace_back(&blueprint);
+
1204  }
+
1205  else
+
1206  throw std::runtime_error("blueprint \"" + blueprint.prefix_ + "\" already exists in blueprint \"" + prefix_ + '\"');
+
1207  }
+
1208 
+
1209 
+
1210  CatchallRule& catchall_rule()
+
1211  {
+
1212  return catchall_rule_;
+
1213  }
+
1214 
+
1215  template<typename App, typename... Middlewares>
+
1216  void middlewares()
+
1217  {
+
1218  mw_indices_.push<App, Middlewares...>();
+
1219  }
+
1220 
+
1221  private:
+
1222  void apply_blueprint(Blueprint& blueprint)
+
1223  {
+
1224 
+
1225  blueprint.prefix_ = prefix_ + '/' + blueprint.prefix_;
+
1226  blueprint.static_dir_ = static_dir_ + '/' + blueprint.static_dir_;
+
1227  blueprint.templates_dir_ = templates_dir_ + '/' + blueprint.templates_dir_;
+
1228  for (auto& rule : blueprint.all_rules_)
+
1229  {
+
1230  std::string new_rule = '/' + prefix_ + rule->rule_;
+
1231  rule->rule_ = new_rule;
+
1232  }
+
1233  for (Blueprint* bp_child : blueprint.blueprints_)
+
1234  {
+
1235  Blueprint& bp_ref = *bp_child;
+
1236  apply_blueprint(bp_ref);
+
1237  }
+
1238  }
+
1239 
+
1240  std::string prefix_;
+
1241  std::string static_dir_;
+
1242  std::string templates_dir_;
+
1243  std::vector<std::unique_ptr<BaseRule>> all_rules_;
+
1244  CatchallRule catchall_rule_;
+
1245  std::vector<Blueprint*> blueprints_;
+
1246  detail::middleware_indices mw_indices_;
+
1247  bool added_{false};
+
1248 
+
1249  friend class Router;
+
1250  };
+
1251 
+
1252  /// Handles matching requests to existing rules and upgrade requests.
+
1253  class Router
+
1254  {
+
1255  public:
+
1256  Router()
+
1257  {}
+
1258 
+
1259  DynamicRule& new_rule_dynamic(const std::string& rule)
+
1260  {
+
1261  auto ruleObject = new DynamicRule(rule);
+
1262  all_rules_.emplace_back(ruleObject);
+
1263 
+
1264  return *ruleObject;
+
1265  }
+
1266 
+
1267  template<uint64_t N>
+
1268  typename black_magic::arguments<N>::type::template rebind<TaggedRule>& new_rule_tagged(const std::string& rule)
+
1269  {
+
1270  using RuleT = typename black_magic::arguments<N>::type::template rebind<TaggedRule>;
+
1271 
+
1272  auto ruleObject = new RuleT(rule);
+
1273  all_rules_.emplace_back(ruleObject);
+
1274 
+
1275  return *ruleObject;
+
1276  }
+
1277 
+
1278  CatchallRule& catchall_rule()
+
1279  {
+
1280  return catchall_rule_;
+
1281  }
+
1282 
+
1283  void internal_add_rule_object(const std::string& rule, BaseRule* ruleObject)
+
1284  {
+
1285  internal_add_rule_object(rule, ruleObject, INVALID_BP_ID, blueprints_);
+
1286  }
+
1287 
+
1288  void internal_add_rule_object(const std::string& rule, BaseRule* ruleObject, const uint16_t& BP_index, std::vector<Blueprint*>& blueprints)
+
1289  {
+
1290  bool has_trailing_slash = false;
+
1291  std::string rule_without_trailing_slash;
+
1292  if (rule.size() > 1 && rule.back() == '/')
+
1293  {
+
1294  has_trailing_slash = true;
+
1295  rule_without_trailing_slash = rule;
+
1296  rule_without_trailing_slash.pop_back();
+
1297  }
+
1298 
+
1299  ruleObject->mw_indices_.pack();
+
1300 
+
1301  ruleObject->foreach_method([&](int method) {
+
1302  per_methods_[method].rules.emplace_back(ruleObject);
+
1303  per_methods_[method].trie.add(rule, per_methods_[method].rules.size() - 1, BP_index != INVALID_BP_ID ? blueprints[BP_index]->prefix().length() : 0, BP_index);
+
1304 
+
1305  // directory case:
+
1306  // request to '/about' url matches '/about/' rule
+
1307  if (has_trailing_slash)
+
1308  {
+
1309  per_methods_[method].trie.add(rule_without_trailing_slash, RULE_SPECIAL_REDIRECT_SLASH, BP_index != INVALID_BP_ID ? blueprints[BP_index]->prefix().length() : 0, BP_index);
+
1310  }
+
1311  });
+
1312 
+
1313  ruleObject->set_added();
+
1314  }
+
1315 
+
1316  void register_blueprint(Blueprint& blueprint)
+
1317  {
+
1318  if (std::find(blueprints_.begin(), blueprints_.end(), &blueprint) == blueprints_.end())
+
1319  {
+
1320  blueprints_.emplace_back(&blueprint);
+
1321  }
+
1322  else
+
1323  throw std::runtime_error("blueprint \"" + blueprint.prefix_ + "\" already exists in router");
+
1324  }
+
1325 
+
1326  void get_recursive_child_methods(Blueprint* blueprint, std::vector<HTTPMethod>& methods)
+
1327  {
+
1328  //we only need to deal with children if the blueprint has absolutely no methods (meaning its index won't be added to the trie)
+
1329  if (blueprint->static_dir_.empty() && blueprint->all_rules_.empty())
+
1330  {
+
1331  for (Blueprint* bp : blueprint->blueprints_)
+
1332  {
+
1333  get_recursive_child_methods(bp, methods);
+
1334  }
+
1335  }
+
1336  else if (!blueprint->static_dir_.empty())
+
1337  methods.emplace_back(HTTPMethod::Get);
+
1338  for (auto& rule : blueprint->all_rules_)
+
1339  {
+
1340  rule->foreach_method([&methods](unsigned method) {
+
1341  HTTPMethod method_final = static_cast<HTTPMethod>(method);
+
1342  if (std::find(methods.begin(), methods.end(), method_final) == methods.end())
+
1343  methods.emplace_back(method_final);
+
1344  });
+
1345  }
+
1346  }
+
1347 
+
1348  void validate_bp() {
+
1349  //Take all the routes from the registered blueprints and add them to `all_rules_` to be processed.
+
1350  detail::middleware_indices blueprint_mw;
+
1351  validate_bp(blueprints_, blueprint_mw);
+
1352  }
+
1353 
+
1354  void validate_bp(std::vector<Blueprint*> blueprints, detail::middleware_indices& current_mw)
+
1355  {
+
1356  for (unsigned i = 0; i < blueprints.size(); i++)
+
1357  {
+
1358  Blueprint* blueprint = blueprints[i];
+
1359 
+
1360  if (blueprint->is_added()) continue;
+
1361 
+
1362  if (blueprint->static_dir_ == "" && blueprint->all_rules_.empty())
+
1363  {
+
1364  std::vector<HTTPMethod> methods;
+
1365  get_recursive_child_methods(blueprint, methods);
+
1366  for (HTTPMethod x : methods)
+
1367  {
+
1368  int i = static_cast<int>(x);
+
1369  per_methods_[i].trie.add(blueprint->prefix(), 0, blueprint->prefix().length(), i);
+
1370  }
+
1371  }
+
1372 
+
1373  current_mw.merge_back(blueprint->mw_indices_);
+
1374  for (auto& rule : blueprint->all_rules_)
+
1375  {
+
1376  if (rule && !rule->is_added())
+
1377  {
+
1378  auto upgraded = rule->upgrade();
+
1379  if (upgraded)
+
1380  rule = std::move(upgraded);
+
1381  rule->validate();
+
1382  rule->mw_indices_.merge_front(current_mw);
+
1383  internal_add_rule_object(rule->rule(), rule.get(), i, blueprints);
+
1384  }
+
1385  }
+
1386  validate_bp(blueprint->blueprints_, current_mw);
+
1387  current_mw.pop_back(blueprint->mw_indices_);
+
1388  blueprint->set_added();
+
1389  }
+
1390  }
+
1391 
+
1392  void validate()
+
1393  {
+
1394  for (auto& rule : all_rules_)
+
1395  {
+
1396  if (rule && !rule->is_added())
+
1397  {
+
1398  auto upgraded = rule->upgrade();
+
1399  if (upgraded)
+
1400  rule = std::move(upgraded);
+
1401  rule->validate();
+
1402  internal_add_rule_object(rule->rule(), rule.get());
+
1403  }
+
1404  }
+
1405  for (auto& per_method : per_methods_)
+
1406  {
+
1407  per_method.trie.validate();
+
1408  }
+
1409  }
+
1410 
+
1411  // TODO maybe add actual_method
+
1412  template<typename Adaptor>
+
1413  void handle_upgrade(const request& req, response& res, Adaptor&& adaptor)
+
1414  {
+
1415  if (req.method >= HTTPMethod::InternalMethodCount)
+
1416  return;
+
1417 
+
1418  auto& per_method = per_methods_[static_cast<int>(req.method)];
+
1419  auto& rules = per_method.rules;
+
1420  unsigned rule_index = per_method.trie.find(req.url).rule_index;
+
1421 
+
1422  if (!rule_index)
+
1423  {
+
1424  for (auto& per_method : per_methods_)
+
1425  {
+
1426  if (per_method.trie.find(req.url).rule_index)
+
1427  {
+
1428  CROW_LOG_DEBUG << "Cannot match method " << req.url << " " << method_name(req.method);
+
1429  res = response(405);
+
1430  res.end();
+
1431  return;
+
1432  }
+
1433  }
+
1434 
+
1435  CROW_LOG_INFO << "Cannot match rules " << req.url;
+
1436  res = response(404);
+
1437  res.end();
+
1438  return;
+
1439  }
+
1440 
+
1441  if (rule_index >= rules.size())
+
1442  throw std::runtime_error("Trie internal structure corrupted!");
+
1443 
+
1444  if (rule_index == RULE_SPECIAL_REDIRECT_SLASH)
+
1445  {
+
1446  CROW_LOG_INFO << "Redirecting to a url with trailing slash: " << req.url;
+
1447  res = response(301);
+
1448 
+
1449  // TODO(ipkn) absolute url building
+
1450  if (req.get_header_value("Host").empty())
+
1451  {
+
1452  res.add_header("Location", req.url + "/");
+
1453  }
+
1454  else
+
1455  {
+
1456  res.add_header("Location", "http://" + req.get_header_value("Host") + req.url + "/");
+
1457  }
+
1458  res.end();
+
1459  return;
+
1460  }
+
1461 
+
1462  CROW_LOG_DEBUG << "Matched rule (upgrade) '" << rules[rule_index]->rule_ << "' " << static_cast<uint32_t>(req.method) << " / " << rules[rule_index]->get_methods();
+
1463 
+
1464  try
+
1465  {
+
1466  rules[rule_index]->handle_upgrade(req, res, std::move(adaptor));
+
1467  }
+
1468  catch (...)
+
1469  {
+
1470  exception_handler_(res);
+
1471  res.end();
+
1472  return;
+
1473  }
+
1474  }
+
1475 
+
1476  void get_found_bp(std::vector<uint16_t>& bp_i, std::vector<Blueprint*>& blueprints, std::vector<Blueprint*>& found_bps, uint16_t index = 0)
+
1477  {
+
1478  // This statement makes 3 assertions:
+
1479  // 1. The index is above 0.
+
1480  // 2. The index does not lie outside the given blueprint list.
+
1481  // 3. The next blueprint we're adding has a prefix that starts the same as the already added blueprint + a slash (the rest is irrelevant).
+
1482  //
+
1483  // This is done to prevent a blueprint that has a prefix of "bp_prefix2" to be assumed as a child of one that has "bp_prefix".
+
1484  //
+
1485  // If any of the assertions is untrue, we delete the last item added, and continue using the blueprint list of the blueprint found before, the topmost being the router's list
+
1486  auto verify_prefix = [&bp_i, &index, &blueprints, &found_bps]() {
+
1487  return index > 0 &&
+
1488  bp_i[index] < blueprints.size() &&
+
1489  blueprints[bp_i[index]]->prefix().substr(0, found_bps[index - 1]->prefix().length() + 1).compare(std::string(found_bps[index - 1]->prefix() + '/')) == 0;
+
1490  };
+
1491  if (index < bp_i.size())
+
1492  {
+
1493 
+
1494  if (verify_prefix())
+
1495  {
+
1496  found_bps.push_back(blueprints[bp_i[index]]);
+
1497  get_found_bp(bp_i, found_bps.back()->blueprints_, found_bps, ++index);
+
1498  }
+
1499  else
+
1500  {
+
1501  if (found_bps.size() < 2)
+
1502  {
+
1503  found_bps.clear();
+
1504  found_bps.push_back(blueprints_[bp_i[index]]);
+
1505  }
+
1506  else
+
1507  {
+
1508  found_bps.pop_back();
+
1509  Blueprint* last_element = found_bps.back();
+
1510  found_bps.push_back(last_element->blueprints_[bp_i[index]]);
+
1511  }
+
1512  get_found_bp(bp_i, found_bps.back()->blueprints_, found_bps, ++index);
+
1513  }
+
1514  }
+
1515  }
+
1516 
+
1517  /// Is used to handle errors, you insert the error code, found route, request, and response. and it'll either call the appropriate catchall route (considering the blueprint system) and send you a status string (which is mainly used for debug messages), or just set the response code to the proper error code.
+
1518  std::string get_error(unsigned short code, routing_handle_result& found, const request& req, response& res)
+
1519  {
+
1520  res.code = code;
+
1521  std::vector<Blueprint*> bps_found;
+
1522  get_found_bp(found.blueprint_indices, blueprints_, bps_found);
+
1523  for (int i = bps_found.size() - 1; i > 0; i--)
+
1524  {
+
1525  std::vector<uint16_t> bpi = found.blueprint_indices;
+
1526  if (bps_found[i]->catchall_rule().has_handler())
+
1527  {
+
1528  try
+
1529  {
+
1530  bps_found[i]->catchall_rule().handler_(req, res);
+
1531  }
+
1532  catch (...)
+
1533  {
+
1534  exception_handler_(res);
+
1535  }
+
1536 #ifdef CROW_ENABLE_DEBUG
+
1537  return std::string("Redirected to Blueprint \"" + bps_found[i]->prefix() + "\" Catchall rule");
+
1538 #else
+
1539  return std::string();
+
1540 #endif
+
1541  }
+
1542  }
+
1543  if (catchall_rule_.has_handler())
+
1544  {
+
1545  try
+
1546  {
+
1547  catchall_rule_.handler_(req, res);
+
1548  }
+
1549  catch (...)
+
1550  {
+
1551  exception_handler_(res);
+
1552  }
+
1553 #ifdef CROW_ENABLE_DEBUG
+
1554  return std::string("Redirected to global Catchall rule");
+
1555 #else
+
1556  return std::string();
+
1557 #endif
+
1558  }
+
1559  return std::string();
+
1560  }
+
1561 
+
1562  std::unique_ptr<routing_handle_result> handle_initial(request& req, response& res)
+
1563  {
+
1564  HTTPMethod method_actual = req.method;
+
1565 
+
1566  std::unique_ptr<routing_handle_result> found{
+ +
1568  0,
+
1569  std::vector<uint16_t>(),
+
1570  routing_params(),
+
1571  HTTPMethod::InternalMethodCount)}; // This is always returned to avoid a null pointer dereference.
+
1572 
+
1573  // NOTE(EDev): This most likely will never run since the parser should handle this situation and close the connection before it gets here.
+
1574  if (CROW_UNLIKELY(req.method >= HTTPMethod::InternalMethodCount))
+
1575  return found;
+
1576  else if (req.method == HTTPMethod::Head)
+
1577  {
+
1578  *found = per_methods_[static_cast<int>(method_actual)].trie.find(req.url);
+
1579  // support HEAD requests using GET if not defined as method for the requested URL
+
1580  if (!found->rule_index)
+
1581  {
+
1582  method_actual = HTTPMethod::Get;
+
1583  *found = per_methods_[static_cast<int>(method_actual)].trie.find(req.url);
+
1584  if (!found->rule_index) // If a route is still not found, return a 404 without executing the rest of the HEAD specific code.
+
1585  {
+
1586  CROW_LOG_DEBUG << "Cannot match rules " << req.url;
+
1587  res = response(404); //TODO(EDev): Should this redirect to catchall?
+
1588  res.end();
+
1589  return found;
+
1590  }
+
1591  }
+
1592 
+
1593  res.skip_body = true;
+
1594  found->method = method_actual;
+
1595  return found;
+
1596  }
+
1597  else if (req.method == HTTPMethod::Options)
+
1598  {
+
1599  std::string allow = "OPTIONS, HEAD, ";
+
1600 
+
1601  if (req.url == "/*")
+
1602  {
+
1603  for (int i = 0; i < static_cast<int>(HTTPMethod::InternalMethodCount); i++)
+
1604  {
+
1605  if (static_cast<int>(HTTPMethod::Head) == i)
+
1606  continue; // HEAD is always allowed
+
1607 
+
1608  if (!per_methods_[i].trie.is_empty())
+
1609  {
+
1610  allow += method_name(static_cast<HTTPMethod>(i)) + ", ";
+
1611  }
+
1612  }
+
1613  allow = allow.substr(0, allow.size() - 2);
+
1614  res = response(204);
+
1615  res.set_header("Allow", allow);
+
1616  res.end();
+
1617  found->method = method_actual;
+
1618  return found;
+
1619  }
+
1620  else
+
1621  {
+
1622  bool rules_matched = false;
+
1623  for (int i = 0; i < static_cast<int>(HTTPMethod::InternalMethodCount); i++)
+
1624  {
+
1625  if (per_methods_[i].trie.find(req.url).rule_index)
+
1626  {
+
1627  rules_matched = true;
+
1628 
+
1629  if (static_cast<int>(HTTPMethod::Head) == i)
+
1630  continue; // HEAD is always allowed
+
1631 
+
1632  allow += method_name(static_cast<HTTPMethod>(i)) + ", ";
+
1633  }
+
1634  }
+
1635  if (rules_matched)
+
1636  {
+
1637  allow = allow.substr(0, allow.size() - 2);
+
1638  res = response(204);
+
1639  res.set_header("Allow", allow);
+
1640  res.end();
+
1641  found->method = method_actual;
+
1642  return found;
+
1643  }
+
1644  else
+
1645  {
+
1646  CROW_LOG_DEBUG << "Cannot match rules " << req.url;
+
1647  res = response(404); //TODO(EDev): Should this redirect to catchall?
+
1648  res.end();
+
1649  return found;
+
1650  }
+
1651  }
+
1652  }
+
1653  else // Every request that isn't a HEAD or OPTIONS request
+
1654  {
+
1655  *found = per_methods_[static_cast<int>(method_actual)].trie.find(req.url);
+
1656  // TODO(EDev): maybe ending the else here would allow the requests coming from above (after removing the return statement) to be checked on whether they actually point to a route
+
1657  if (!found->rule_index)
+
1658  {
+
1659  for (auto& per_method : per_methods_)
+
1660  {
+
1661  if (per_method.trie.find(req.url).rule_index) //Route found, but in another method
+
1662  {
+
1663  const std::string error_message(get_error(405, *found, req, res));
+
1664  CROW_LOG_DEBUG << "Cannot match method " << req.url << " " << method_name(method_actual) << ". " << error_message;
+
1665  res.end();
+
1666  return found;
+
1667  }
+
1668  }
+
1669  //Route does not exist anywhere
+
1670 
+
1671  const std::string error_message(get_error(404, *found, req, res));
+
1672  CROW_LOG_DEBUG << "Cannot match rules " << req.url << ". " << error_message;
+
1673  res.end();
+
1674  return found;
+
1675  }
+
1676 
+
1677  found->method = method_actual;
+
1678  return found;
+
1679  }
+
1680  }
+
1681 
+
1682  template<typename App>
+
1683  void handle(request& req, response& res, routing_handle_result found)
+
1684  {
+
1685  HTTPMethod method_actual = found.method;
+
1686  auto& rules = per_methods_[static_cast<int>(method_actual)].rules;
+
1687  unsigned rule_index = found.rule_index;
+
1688 
+
1689  if (rule_index >= rules.size())
+
1690  throw std::runtime_error("Trie internal structure corrupted!");
+
1691 
+
1692  if (rule_index == RULE_SPECIAL_REDIRECT_SLASH)
+
1693  {
+
1694  CROW_LOG_INFO << "Redirecting to a url with trailing slash: " << req.url;
+
1695  res = response(301);
+
1696 
+
1697  // TODO(ipkn) absolute url building
+
1698  if (req.get_header_value("Host").empty())
+
1699  {
+
1700  res.add_header("Location", req.url + "/");
+
1701  }
+
1702  else
+
1703  {
+
1704  res.add_header("Location", "http://" + req.get_header_value("Host") + req.url + "/");
+
1705  }
+
1706  res.end();
+
1707  return;
+
1708  }
+
1709 
+
1710  CROW_LOG_DEBUG << "Matched rule '" << rules[rule_index]->rule_ << "' " << static_cast<uint32_t>(req.method) << " / " << rules[rule_index]->get_methods();
+
1711 
+
1712  try
+
1713  {
+
1714  auto& rule = rules[rule_index];
+
1715  handle_rule<App>(rule, req, res, found.r_params);
+
1716  }
+
1717  catch (...)
+
1718  {
+
1719  exception_handler_(res);
+
1720  res.end();
+
1721  return;
+
1722  }
+
1723  }
+
1724 
+
1725  template<typename App>
+
1726  typename std::enable_if<std::tuple_size<typename App::mw_container_t>::value != 0, void>::type
+
1727  handle_rule(BaseRule* rule, crow::request& req, crow::response& res, const crow::routing_params& rp)
+
1728  {
+
1729  if (!rule->mw_indices_.empty())
+
1730  {
+
1731  auto& ctx = *reinterpret_cast<typename App::context_t*>(req.middleware_context);
+
1732  auto& container = *reinterpret_cast<typename App::mw_container_t*>(req.middleware_container);
+
1733  detail::middleware_call_criteria_dynamic<false> crit_fwd(rule->mw_indices_.indices());
+
1734 
+
1735  auto glob_completion_handler = std::move(res.complete_request_handler_);
+
1736  res.complete_request_handler_ = [] {};
+
1737 
+
1738  detail::middleware_call_helper<decltype(crit_fwd),
+
1739  0, typename App::context_t, typename App::mw_container_t>(crit_fwd, container, req, res, ctx);
+
1740 
+
1741  if (res.completed_)
+
1742  {
+
1743  glob_completion_handler();
+
1744  return;
+
1745  }
+
1746 
+
1747  res.complete_request_handler_ = [&rule, &ctx, &container, &req, &res, glob_completion_handler] {
+
1748  detail::middleware_call_criteria_dynamic<true> crit_bwd(rule->mw_indices_.indices());
+
1749 
+
1750  detail::after_handlers_call_helper<
+
1751  decltype(crit_bwd),
+
1752  std::tuple_size<typename App::mw_container_t>::value - 1,
+
1753  typename App::context_t,
+
1754  typename App::mw_container_t>(crit_bwd, container, ctx, req, res);
+
1755  glob_completion_handler();
+
1756  };
+
1757  }
+
1758  rule->handle(req, res, rp);
+
1759  }
+
1760 
+
1761  template<typename App>
+
1762  typename std::enable_if<std::tuple_size<typename App::mw_container_t>::value == 0, void>::type
+
1763  handle_rule(BaseRule* rule, crow::request& req, crow::response& res, const crow::routing_params& rp)
+
1764  {
+
1765  rule->handle(req, res, rp);
+
1766  }
+
1767 
+
1768  void debug_print()
+
1769  {
+
1770  for (int i = 0; i < static_cast<int>(HTTPMethod::InternalMethodCount); i++)
+
1771  {
+
1772  Trie& trie_ = per_methods_[i].trie;
+
1773  if (!trie_.is_empty())
+
1774  {
+
1775  CROW_LOG_DEBUG << method_name(static_cast<HTTPMethod>(i));
+
1776  trie_.debug_print();
+
1777  }
+
1778  }
+
1779  }
+
1780 
+
1781  std::vector<Blueprint*>& blueprints()
+
1782  {
+
1783  return blueprints_;
+
1784  }
+
1785 
+
1786  std::function<void(crow::response&)>& exception_handler()
+
1787  {
+
1788  return exception_handler_;
+
1789  }
+
1790 
+
1791  static void default_exception_handler(response& res)
+
1792  {
+
1793  // any uncaught exceptions become 500s
+
1794  res = response(500);
+
1795 
+
1796  try
+
1797  {
+
1798  throw;
+
1799  }
+
1800  catch (const std::exception& e)
+
1801  {
+
1802  CROW_LOG_ERROR << "An uncaught exception occurred: " << e.what();
+
1803  }
+
1804  catch (...)
+
1805  {
+
1806  CROW_LOG_ERROR << "An uncaught exception occurred. The type was unknown so no information was available.";
+
1807  }
+
1808  }
+
1809 
+
1810  private:
+
1811  CatchallRule catchall_rule_;
+
1812 
+
1813  struct PerMethod
+
1814  {
+
1815  std::vector<BaseRule*> rules;
+
1816  Trie trie;
+
1817 
+
1818  // rule index 0, 1 has special meaning; preallocate it to avoid duplication.
+
1819  PerMethod():
+
1820  rules(2) {}
+
1821  };
+
1822  std::array<PerMethod, static_cast<int>(HTTPMethod::InternalMethodCount)> per_methods_;
+
1823  std::vector<std::unique_ptr<BaseRule>> all_rules_;
+
1824  std::vector<Blueprint*> blueprints_;
+
1825  std::function<void(crow::response&)> exception_handler_ = &default_exception_handler;
+
1826  };
+
1827 } // namespace crow
+
A base class for all rules.
Definition: routing.h:89
+
A blueprint can be considered a smaller section of a Crow app, specifically where the router is conec...
Definition: routing.h:1104
+
Definition: routing.h:342
+
The main server application class.
Definition: app.h:199
+
self_t & websocket_max_payload(uint64_t max_payload)
Set the default max payload size for websockets.
Definition: app.h:278
+
A rule that can change its parameters during runtime.
Definition: routing.h:575
+
Handles matching requests to existing rules and upgrade requests.
Definition: routing.h:1254
+
std::string get_error(unsigned short code, routing_handle_result &found, const request &req, response &res)
Is used to handle errors, you insert the error code, found route, request, and response....
Definition: routing.h:1518
+
Default rule created when CROW_ROUTE is called.
Definition: routing.h:652
+
A search tree.
Definition: routing.h:716
+
bool is_empty()
Check whether or not the trie is empty.
Definition: routing.h:750
+
A rule dealing with websockets.
Definition: routing.h:442
+
self_t & max_payload(uint64_t max_payload)
Override the global payload limit for this single WebSocket rule.
Definition: routing.h:474
+
A websocket connection.
Definition: websocket.h:81
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
Crow< Middlewares... > App
Alias of Crow<Middlewares...>. Useful if you want a instance of an Crow application that require Midd...
Definition: app.h:771
+
Allows the user to assign parameters using functions.
Definition: routing.h:533
+
self_t & middlewares()
Enable local middleware for this handler.
Definition: routing.h:566
+
Definition: socket_adaptors.h:107
+
A wrapper for the asio::ip::tcp::socket and asio::ssl::stream.
Definition: socket_adaptors.h:39
+
Definition: routing.h:719
+
Typesafe wrapper for storing lists of middleware as their indices in the App.
Definition: routing.h:30
+ + + + + + +
An HTTP request.
Definition: http_request.h:36
+
std::string url
The endpoint without any parameters.
Definition: http_request.h:39
+
HTTP response.
Definition: http_response.h:34
+
void add_header(std::string key, std::string value)
Add a new header to the response.
Definition: http_response.h:58
+
bool skip_body
Whether this is a response to a HEAD request.
Definition: http_response.h:47
+
int code
The Status code for the response.
Definition: http_response.h:40
+
void set_header(std::string key, std::string value)
Set the value of an existing header in the response.
Definition: http_response.h:51
+
void end()
Set the response completion flag and call the handler (to send the response).
Definition: http_response.h:237
+
Definition: common.h:281
+
A base class for websocket connection.
Definition: websocket.h:38
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/search/all_0.html b/1.2/reference/search/all_0.html new file mode 100644 index 000000000..1ec5b2d59 --- /dev/null +++ b/1.2/reference/search/all_0.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_0.js b/1.2/reference/search/all_0.js new file mode 100644 index 000000000..74cfc0e93 --- /dev/null +++ b/1.2/reference/search/all_0.js @@ -0,0 +1,11 @@ +var searchData= +[ + ['action_0',['Action',['../structcrow_1_1mustache_1_1_action.html',1,'crow::mustache']]], + ['add_1',['add',['../structcrow_1_1session_1_1_expiration_tracker.html#a82f229b28c67ea4adfaae80db9628824',1,'crow::session::ExpirationTracker']]], + ['add_5fblueprint_2',['add_blueprint',['../classcrow_1_1_crow.html#af0d01b97da7d4d20844a80fd31b74f46',1,'crow::Crow']]], + ['add_5fheader_3',['add_header',['../structcrow_1_1response.html#a16d1a8bcec6460ba97f90b80881693b8',1,'crow::response']]], + ['add_5fstatic_5fdir_4',['add_static_dir',['../classcrow_1_1_crow.html#a3cbe89120e47d2bd3d05376b9129adfa',1,'crow::Crow']]], + ['allow_5fcredentials_5',['allow_credentials',['../structcrow_1_1_c_o_r_s_rules.html#abca9739b2819cb386123997aab7b0dec',1,'crow::CORSRules']]], + ['app_6',['App',['../namespacecrow.html#a153c1bf24903d1a8629ef6eaf045110b',1,'crow']]], + ['app_2eh_7',['app.h',['../app_8h.html',1,'']]] +]; diff --git a/1.2/reference/search/all_1.html b/1.2/reference/search/all_1.html new file mode 100644 index 000000000..9f80e9043 --- /dev/null +++ b/1.2/reference/search/all_1.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_1.js b/1.2/reference/search/all_1.js new file mode 100644 index 000000000..898d36f0e --- /dev/null +++ b/1.2/reference/search/all_1.js @@ -0,0 +1,11 @@ +var searchData= +[ + ['b_8',['b',['../classcrow_1_1json_1_1rvalue.html#a61a5f98c6b0257d53c60a70eeff15490',1,'crow::json::rvalue']]], + ['baserule_9',['BaseRule',['../classcrow_1_1_base_rule.html',1,'crow']]], + ['bindaddr_10',['bindaddr',['../classcrow_1_1_crow.html#a75777f82b6519c86d71446eb9285d774',1,'crow::Crow::bindaddr(std::string bindaddr)'],['../classcrow_1_1_crow.html#a8c816534804e7bd351ca692005bf3343',1,'crow::Crow::bindaddr()']]], + ['blueprint_11',['blueprint',['../structcrow_1_1_c_o_r_s_rules.html#ac26c50868a334cdd3601c7cd2f2a5248',1,'crow::CORSRules::blueprint()'],['../structcrow_1_1_c_o_r_s_handler.html#a218d078e061f8d2ad4c16e7db6022cad',1,'crow::CORSHandler::blueprint()']]], + ['blueprint_12',['Blueprint',['../classcrow_1_1_blueprint.html',1,'crow']]], + ['body_13',['body',['../structcrow_1_1response.html#ae9f3cc153eac05954f1f4e599527892d',1,'crow::response::body()'],['../structcrow_1_1multipart_1_1part.html#acbfa0a181e86a89dccdf70d985365695',1,'crow::multipart::part::body()']]], + ['boundary_14',['boundary',['../structcrow_1_1multipart_1_1message.html#a56eb4bbf64d4930663ac4d5dd7b77d34',1,'crow::multipart::message']]], + ['build_5fheader_15',['build_header',['../classcrow_1_1websocket_1_1_connection.html#a2fc995281b9452b56f743294baa7ed17',1,'crow::websocket::Connection']]] +]; diff --git a/1.2/reference/search/all_10.html b/1.2/reference/search/all_10.html new file mode 100644 index 000000000..3bf11961f --- /dev/null +++ b/1.2/reference/search/all_10.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_10.js b/1.2/reference/search/all_10.js new file mode 100644 index 000000000..18e32dc9d --- /dev/null +++ b/1.2/reference/search/all_10.js @@ -0,0 +1,27 @@ +var searchData= +[ + ['r_5fstring_163',['r_string',['../structcrow_1_1json_1_1detail_1_1r__string.html',1,'crow::json::detail']]], + ['raw_5fsocket_164',['raw_socket',['../structcrow_1_1_socket_adaptor.html#a6c1efabfc9bf922308027f3d35c1f2c7',1,'crow::SocketAdaptor']]], + ['raw_5furl_165',['raw_url',['../structcrow_1_1request.html#a72f5504a56f9ba70d7d33f86aaf9bc8a',1,'crow::request']]], + ['redirect_166',['redirect',['../structcrow_1_1response.html#ac04bbe2d4f54fd717cdffdb26af3e46f',1,'crow::response']]], + ['redirect_5fperm_167',['redirect_perm',['../structcrow_1_1response.html#a9e87a17c3cf8b434fd2a64a9b3d4b675',1,'crow::response']]], + ['remote_5fip_5faddress_168',['remote_ip_address',['../structcrow_1_1request.html#aa8a04e30e2249f04614f233d25ffaad7',1,'crow::request']]], + ['render_169',['render',['../classcrow_1_1mustache_1_1template__t.html#ae8f2561efe590c0b5704df76b0c82aa5',1,'crow::mustache::template_t::render(const context &&ctx) const'],['../classcrow_1_1mustache_1_1template__t.html#a77c579b71240695bd9fb634f48facd03',1,'crow::mustache::template_t::render(const context &ctx) const'],['../classcrow_1_1mustache_1_1template__t.html#a67caf7e23349a829b913c897ab882a8e',1,'crow::mustache::template_t::render() const']]], + ['render_5fstring_170',['render_string',['../classcrow_1_1mustache_1_1template__t.html#af2258136c497b02eadfacbf50704de08',1,'crow::mustache::template_t::render_string(const context &ctx) const'],['../classcrow_1_1mustache_1_1template__t.html#a21199e08a066d7c66b5728354c2c40fd',1,'crow::mustache::template_t::render_string() const']]], + ['rendered_5ftemplate_171',['rendered_template',['../structcrow_1_1mustache_1_1rendered__template.html',1,'crow::mustache']]], + ['req_172',['req',['../structcrow_1_1_h_t_t_p_parser.html#a56ce939040d6c582a62cea766e489d53',1,'crow::HTTPParser']]], + ['req_5fhandler_5fwrapper_173',['req_handler_wrapper',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.html',1,'crow::detail::routing_handler_call_helper::Wrapped']]], + ['request_174',['request',['../structcrow_1_1request.html',1,'crow::request'],['../structcrow_1_1request.html#a838c9a8c9a5eb2283d57e66f3630b5a6',1,'crow::request::request()'],['../structcrow_1_1request.html#a111b70ddb2a100a79415b539e152e145',1,'crow::request::request(HTTPMethod method, std::string raw_url, std::string url, query_string url_params, ci_map headers, std::string body, unsigned char http_major, unsigned char http_minor, bool has_keep_alive, bool has_close_connection, bool is_upgrade)']]], + ['response_175',['response',['../structcrow_1_1response.html',1,'crow']]], + ['returnable_176',['returnable',['../structcrow_1_1returnable.html',1,'crow']]], + ['route_177',['route',['../classcrow_1_1_crow.html#a5e1e54d49ff3015fd08f545b574ab44f',1,'crow::Crow']]], + ['route_5fdynamic_178',['route_dynamic',['../classcrow_1_1_crow.html#a0822a573ed653c3218f06c819a773ec2',1,'crow::Crow']]], + ['router_179',['Router',['../classcrow_1_1_router.html',1,'crow']]], + ['routing_5fhandle_5fresult_180',['routing_handle_result',['../structcrow_1_1routing__handle__result.html',1,'crow']]], + ['ruleparametertraits_181',['RuleParameterTraits',['../structcrow_1_1_rule_parameter_traits.html',1,'crow']]], + ['ruleparametertraits_3c_20dynamicrule_20_3e_182',['RuleParameterTraits< DynamicRule >',['../structcrow_1_1_rule_parameter_traits.html',1,'crow']]], + ['ruleparametertraits_3c_20taggedrule_3c_20args_2e_2e_2e_20_3e_20_3e_183',['RuleParameterTraits< TaggedRule< Args... > >',['../structcrow_1_1_rule_parameter_traits.html',1,'crow']]], + ['run_184',['run',['../classcrow_1_1_crow.html#a193d8b03f717234a841cd92f72c6b4b5',1,'crow::Crow']]], + ['run_5fasync_185',['run_async',['../classcrow_1_1_crow.html#aac4f72d944fb35caaf2d82cd21287269',1,'crow::Crow']]], + ['rvalue_186',['rvalue',['../classcrow_1_1json_1_1rvalue.html',1,'crow::json']]] +]; diff --git a/1.2/reference/search/all_11.html b/1.2/reference/search/all_11.html new file mode 100644 index 000000000..c9f79d289 --- /dev/null +++ b/1.2/reference/search/all_11.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_11.js b/1.2/reference/search/all_11.js new file mode 100644 index 000000000..a2eb1e15a --- /dev/null +++ b/1.2/reference/search/all_11.js @@ -0,0 +1,35 @@ +var searchData= +[ + ['s_187',['s',['../classcrow_1_1json_1_1rvalue.html#ad94f27a14e60af841219279f70290858',1,'crow::json::rvalue']]], + ['s_5f_188',['s_',['../structcrow_1_1json_1_1detail_1_1r__string.html#a9a0a048fb2cb904e8336926817947448',1,'crow::json::detail::r_string']]], + ['schedule_189',['schedule',['../classcrow_1_1detail_1_1task__timer.html#ac1a35eb9b85887368b65e01c07d3c91c',1,'crow::detail::task_timer::schedule(const task_type &task)'],['../classcrow_1_1detail_1_1task__timer.html#a777c073f4e895c638d2cbbf6a27ad1fa',1,'crow::detail::task_timer::schedule(const task_type &task, std::uint8_t timeout)']]], + ['self_5ft_190',['self_t',['../classcrow_1_1_crow.html#a5b0a203a6f9070ea8010227dcdbcec60',1,'crow::Crow']]], + ['send_5fbinary_191',['send_binary',['../classcrow_1_1websocket_1_1_connection.html#ac8ba4036c9777f0e3af3531791d8ca62',1,'crow::websocket::Connection']]], + ['send_5fping_192',['send_ping',['../classcrow_1_1websocket_1_1_connection.html#ab5c1387014e5fdc0e9ebbb8661be04da',1,'crow::websocket::Connection']]], + ['send_5fpong_193',['send_pong',['../classcrow_1_1websocket_1_1_connection.html#a22c353583685e0e878813ab67333342c',1,'crow::websocket::Connection']]], + ['send_5ftext_194',['send_text',['../classcrow_1_1websocket_1_1_connection.html#a595b84a3c7206d4923286ac863b45ffb',1,'crow::websocket::Connection']]], + ['sendmessagetype_195',['SendMessageType',['../structcrow_1_1websocket_1_1_connection_1_1_send_message_type.html',1,'crow::websocket::Connection']]], + ['server_196',['Server',['../classcrow_1_1_server.html',1,'crow']]], + ['server_5fname_197',['server_name',['../classcrow_1_1_crow.html#ae0e400a1757bd68f716b82753a5a1a73',1,'crow::Crow']]], + ['server_5ft_198',['server_t',['../classcrow_1_1_crow.html#a5df810d2619e31c2f024cc4e45898997',1,'crow::Crow']]], + ['sessionmiddleware_199',['SessionMiddleware',['../structcrow_1_1_session_middleware.html',1,'crow']]], + ['set_5fdefault_5ftimeout_200',['set_default_timeout',['../classcrow_1_1detail_1_1task__timer.html#aa67cab7afc1646a4127b0c6c97e5f5ea',1,'crow::detail::task_timer']]], + ['set_5fheader_201',['set_header',['../structcrow_1_1response.html#ab2b9a9b9795fa6330bd47b66a716cb0b',1,'crow::response']]], + ['set_5fstatic_5ffile_5finfo_202',['set_static_file_info',['../structcrow_1_1response.html#a8f5e5caa08c3e658bccd03996e1a778a',1,'crow::response']]], + ['set_5fstatic_5ffile_5finfo_5funsafe_203',['set_static_file_info_unsafe',['../structcrow_1_1response.html#adaaa1a62451d41e6f3831463296b4c08',1,'crow::response']]], + ['sha1_204',['sha1',['../namespacesha1.html',1,'']]], + ['sha1_205',['SHA1',['../classsha1_1_1_s_h_a1.html',1,'sha1']]], + ['simpleapp_206',['SimpleApp',['../namespacecrow.html#a3603179c9794548cac2c9990685178b4',1,'crow']]], + ['size_207',['size',['../classcrow_1_1json_1_1wvalue.html#a1ded929c63fcb6e3c53be38e9b54c672',1,'crow::json::wvalue']]], + ['skip_5fbody_208',['skip_body',['../structcrow_1_1response.html#a548c4f5e059a7bb3b2560b7ac5800011',1,'crow::response']]], + ['socket_209',['socket',['../classcrow_1_1_connection.html#adb5878dd700c30dae10f3fa8d06ecbab',1,'crow::Connection::socket()'],['../structcrow_1_1_socket_adaptor.html#a70c413ce6d8f9e2fe1e4852fc07f0928',1,'crow::SocketAdaptor::socket()']]], + ['socketadaptor_210',['SocketAdaptor',['../structcrow_1_1_socket_adaptor.html',1,'crow']]], + ['ssl_5fchainfile_211',['ssl_chainfile',['../classcrow_1_1_crow.html#ade6bf7e56805c1112532807581293448',1,'crow::Crow']]], + ['ssl_5ffile_212',['ssl_file',['../classcrow_1_1_crow.html#a987e909347f0563f7b3dd97bbe271cea',1,'crow::Crow::ssl_file(const std::string &crt_filename, const std::string &key_filename)'],['../classcrow_1_1_crow.html#a3e5aa337025914852fcbfd1aebbd3241',1,'crow::Crow::ssl_file(const std::string &pem_filename)']]], + ['ssl_5fserver_5ft_213',['ssl_server_t',['../classcrow_1_1_crow.html#aac04f81d0bc897267d092bb8af1513d4',1,'crow::Crow']]], + ['ssladaptor_214',['SSLAdaptor',['../structcrow_1_1_s_s_l_adaptor.html',1,'crow']]], + ['start_215',['start',['../classcrow_1_1websocket_1_1_connection.html#a928134640aa98a86f56a71735a41147a',1,'crow::websocket::Connection']]], + ['static_5ffile_5finfo_216',['static_file_info',['../structcrow_1_1response_1_1static__file__info.html',1,'crow::response']]], + ['stop_217',['stop',['../classcrow_1_1_crow.html#a0266672657128919ab9a067d93f3868f',1,'crow::Crow']]], + ['stream_5fthreshold_218',['stream_threshold',['../classcrow_1_1_crow.html#ae92390d22f6fc99987c41a617be71d64',1,'crow::Crow::stream_threshold(size_t threshold)'],['../classcrow_1_1_crow.html#a0a7b45c935e58d199eb1bcba86003232',1,'crow::Crow::stream_threshold()']]] +]; diff --git a/1.2/reference/search/all_12.html b/1.2/reference/search/all_12.html new file mode 100644 index 000000000..ab934722c --- /dev/null +++ b/1.2/reference/search/all_12.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_12.js b/1.2/reference/search/all_12.js new file mode 100644 index 000000000..82728881e --- /dev/null +++ b/1.2/reference/search/all_12.js @@ -0,0 +1,11 @@ +var searchData= +[ + ['t_219',['t',['../classcrow_1_1json_1_1rvalue.html#a9c9f7242e4164f4ed690e50e3cf5f4b1',1,'crow::json::rvalue']]], + ['taggedrule_220',['TaggedRule',['../classcrow_1_1_tagged_rule.html',1,'crow']]], + ['task_5ftimer_221',['task_timer',['../classcrow_1_1detail_1_1task__timer.html',1,'crow::detail']]], + ['template_5ft_222',['template_t',['../classcrow_1_1mustache_1_1template__t.html',1,'crow::mustache']]], + ['tick_223',['tick',['../classcrow_1_1_crow.html#a068042431b0be5911ee1689a285f4693',1,'crow::Crow']]], + ['timeout_224',['timeout',['../classcrow_1_1_crow.html#a47ed9a118820f6e6ba0b2bc37f0997fb',1,'crow::Crow']]], + ['tinysha1_2ehpp_225',['TinySHA1.hpp',['../_tiny_s_h_a1_8hpp.html',1,'']]], + ['trie_226',['Trie',['../classcrow_1_1_trie.html',1,'crow']]] +]; diff --git a/1.2/reference/search/all_13.html b/1.2/reference/search/all_13.html new file mode 100644 index 000000000..51172c2f3 --- /dev/null +++ b/1.2/reference/search/all_13.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_13.js b/1.2/reference/search/all_13.js new file mode 100644 index 000000000..7bf01b38a --- /dev/null +++ b/1.2/reference/search/all_13.js @@ -0,0 +1,9 @@ +var searchData= +[ + ['u_227',['u',['../classcrow_1_1json_1_1rvalue.html#a775273fbbe868c7c8d3a71acdb9ee276',1,'crow::json::rvalue']]], + ['unescape_228',['unescape',['../classcrow_1_1json_1_1rvalue.html#a8c60e32c3e25b71c794cc79a4dea466c',1,'crow::json::rvalue']]], + ['upgrade_229',['upgrade',['../structcrow_1_1request.html#ac4b5e2e32e2e0b633211925158b03559',1,'crow::request']]], + ['url_230',['url',['../structcrow_1_1request.html#aa3df34c56847d6d42887e73655276167',1,'crow::request']]], + ['url_5fparams_231',['url_params',['../structcrow_1_1request.html#a745d5a94e9e9ae1fed64674aae0194b0',1,'crow::request']]], + ['utf8_232',['UTF8',['../structcrow_1_1_u_t_f8.html',1,'crow']]] +]; diff --git a/1.2/reference/search/all_14.html b/1.2/reference/search/all_14.html new file mode 100644 index 000000000..afecf5634 --- /dev/null +++ b/1.2/reference/search/all_14.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_14.js b/1.2/reference/search/all_14.js new file mode 100644 index 000000000..26e02706c --- /dev/null +++ b/1.2/reference/search/all_14.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['validate_233',['validate',['../classcrow_1_1_crow.html#ab9a22c981e0afec0d55ee234683a6d38',1,'crow::Crow']]], + ['value_234',['value',['../structcrow_1_1multipart_1_1header.html#aec60ea97914c4b9b102c3d5c1e89330a',1,'crow::multipart::header']]] +]; diff --git a/1.2/reference/search/all_15.html b/1.2/reference/search/all_15.html new file mode 100644 index 000000000..69f382b31 --- /dev/null +++ b/1.2/reference/search/all_15.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_15.js b/1.2/reference/search/all_15.js new file mode 100644 index 000000000..abad56b87 --- /dev/null +++ b/1.2/reference/search/all_15.js @@ -0,0 +1,11 @@ +var searchData= +[ + ['wait_5ffor_5fserver_5fstart_235',['wait_for_server_start',['../classcrow_1_1_crow.html#a5e39821ccc9cbf8c6400fd86fc406c21',1,'crow::Crow']]], + ['wait_5ffor_5fstart_236',['wait_for_start',['../classcrow_1_1_server.html#a0b63b4a3da3acbb2a1870db19279f580',1,'crow::Server']]], + ['weakwrappedmessage_237',['WeakWrappedMessage',['../structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.html',1,'crow::websocket::Connection']]], + ['websocket_5fmax_5fpayload_238',['websocket_max_payload',['../classcrow_1_1_crow.html#a30d9cbcaa6aa3c3e44a8a3c4479fd7cf',1,'crow::Crow::websocket_max_payload(uint64_t max_payload)'],['../classcrow_1_1_crow.html#a391a488c01ce53c0ccfd502c7ad15640',1,'crow::Crow::websocket_max_payload()']]], + ['websocketrule_239',['WebSocketRule',['../classcrow_1_1_web_socket_rule.html',1,'crow']]], + ['wrapped_240',['Wrapped',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html',1,'crow::detail::routing_handler_call_helper']]], + ['wvalue_241',['wvalue',['../classcrow_1_1json_1_1wvalue.html',1,'crow::json::wvalue'],['../classcrow_1_1json_1_1wvalue.html#a1813a29de56af96789cc76b8cdb0dbbe',1,'crow::json::wvalue::wvalue()']]], + ['wvalue_5freader_242',['wvalue_reader',['../structcrow_1_1json_1_1wvalue__reader.html',1,'crow::json']]] +]; diff --git a/1.2/reference/search/all_2.html b/1.2/reference/search/all_2.html new file mode 100644 index 000000000..02cfffc2e --- /dev/null +++ b/1.2/reference/search/all_2.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_2.js b/1.2/reference/search/all_2.js new file mode 100644 index 000000000..b0532f6ba --- /dev/null +++ b/1.2/reference/search/all_2.js @@ -0,0 +1,49 @@ +var searchData= +[ + ['cachedsession_16',['CachedSession',['../structcrow_1_1session_1_1_cached_session.html',1,'crow::session']]], + ['call_17',['call',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_3c_20f_2c_20nint_2c_20nuint_2c_20ndouble_2c_20nstring_2c_20black_5fmagic_3a_3as_3c_20double_2c_20args1_2e_2e_2e_20_3e_2c_20black_5fmagic_3a_3as_3c_20args2_2e_2e_2e_20_3e_20_3e_18',['call< F, NInt, NUint, NDouble, NString, black_magic::S< double, Args1... >, black_magic::S< Args2... > >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_3c_20f_2c_20nint_2c_20nuint_2c_20ndouble_2c_20nstring_2c_20black_5fmagic_3a_3as_3c_20int64_5ft_2c_20args1_2e_2e_2e_20_3e_2c_20black_5fmagic_3a_3as_3c_20args2_2e_2e_2e_20_3e_20_3e_19',['call< F, NInt, NUint, NDouble, NString, black_magic::S< int64_t, Args1... >, black_magic::S< Args2... > >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_3c_20f_2c_20nint_2c_20nuint_2c_20ndouble_2c_20nstring_2c_20black_5fmagic_3a_3as_3c_20std_3a_3astring_2c_20args1_2e_2e_2e_20_3e_2c_20black_5fmagic_3a_3as_3c_20args2_2e_2e_2e_20_3e_20_3e_20',['call< F, NInt, NUint, NDouble, NString, black_magic::S< std::string, Args1... >, black_magic::S< Args2... > >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_3c_20f_2c_20nint_2c_20nuint_2c_20ndouble_2c_20nstring_2c_20black_5fmagic_3a_3as_3c_20uint64_5ft_2c_20args1_2e_2e_2e_20_3e_2c_20black_5fmagic_3a_3as_3c_20args2_2e_2e_2e_20_3e_20_3e_21',['call< F, NInt, NUint, NDouble, NString, black_magic::S< uint64_t, Args1... >, black_magic::S< Args2... > >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_3c_20f_2c_20nint_2c_20nuint_2c_20ndouble_2c_20nstring_2c_20black_5fmagic_3a_3as_3c_3e_2c_20black_5fmagic_3a_3as_3c_20args1_2e_2e_2e_20_3e_20_3e_22',['call< F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S< Args1... > >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_5fpair_23',['call_pair',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_5fparams_24',['call_params',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html',1,'crow::detail::routing_handler_call_helper']]], + ['catchall_5froute_25',['catchall_route',['../classcrow_1_1_crow.html#ab1beefb0c6fc3c534160ba3bbc615069',1,'crow::Crow']]], + ['catchallrule_26',['CatchallRule',['../classcrow_1_1_catchall_rule.html',1,'crow']]], + ['cerrloghandler_27',['CerrLogHandler',['../classcrow_1_1_cerr_log_handler.html',1,'crow']]], + ['check_5fafter_5fhandle_5farity_5f3_28',['check_after_handle_arity_3',['../structcrow_1_1detail_1_1check__after__handle__arity__3.html',1,'crow::detail']]], + ['check_5fafter_5fhandle_5farity_5f3_5fconst_29',['check_after_handle_arity_3_const',['../structcrow_1_1detail_1_1check__after__handle__arity__3__const.html',1,'crow::detail']]], + ['check_5fbefore_5fhandle_5farity_5f3_30',['check_before_handle_arity_3',['../structcrow_1_1detail_1_1check__before__handle__arity__3.html',1,'crow::detail']]], + ['check_5fbefore_5fhandle_5farity_5f3_5fconst_31',['check_before_handle_arity_3_const',['../structcrow_1_1detail_1_1check__before__handle__arity__3__const.html',1,'crow::detail']]], + ['check_5fdestroy_32',['check_destroy',['../classcrow_1_1websocket_1_1_connection.html#a8030e7ca3e9ee5d07ccf7f8cb43fa317',1,'crow::websocket::Connection']]], + ['check_5fglobal_5fcall_5ffalse_33',['check_global_call_false',['../structcrow_1_1detail_1_1check__global__call__false.html',1,'crow::detail']]], + ['ci_5fhash_34',['ci_hash',['../structcrow_1_1ci__hash.html',1,'crow']]], + ['ci_5fkey_5feq_35',['ci_key_eq',['../structcrow_1_1ci__key__eq.html',1,'crow']]], + ['clear_36',['clear',['../classcrow_1_1json_1_1wvalue.html#af46596998d8e639a23b401e951297b63',1,'crow::json::wvalue']]], + ['close_37',['close',['../classcrow_1_1websocket_1_1_connection.html#a663d3f3917b8cc7f9b54e6c7dfc8d604',1,'crow::websocket::Connection']]], + ['close_5fconnection_38',['close_connection',['../structcrow_1_1request.html#a4a3e4bcd0cd626ceaee38f4c17d28c8d',1,'crow::request']]], + ['code_39',['code',['../structcrow_1_1response.html#aabc1f9b3264b8c5a2d05dcb409e8ff3f',1,'crow::response']]], + ['complete_5frequest_40',['complete_request',['../classcrow_1_1_connection.html#aa40019a3731cc55174401e3b31602524',1,'crow::Connection']]], + ['compressed_41',['compressed',['../structcrow_1_1response.html#af87163fd1c7e18650c7691e07f58c7de',1,'crow::response']]], + ['concurrency_42',['concurrency',['../classcrow_1_1_crow.html#abd824d73fdd02ba810b8dd37e2900240',1,'crow::Crow::concurrency()'],['../classcrow_1_1_crow.html#a41686e6025705c1ab379b5ec71bbf983',1,'crow::Crow::concurrency(std::uint16_t concurrency)']]], + ['connection_43',['Connection',['../classcrow_1_1websocket_1_1_connection.html#ae13084d8ea772f54bf3397a9fab107d8',1,'crow::websocket::Connection::Connection()'],['../classcrow_1_1_connection.html',1,'crow::Connection< Adaptor, Handler, Middlewares >']]], + ['connection_44',['connection',['../structcrow_1_1websocket_1_1connection.html',1,'crow::websocket']]], + ['connection_45',['Connection',['../classcrow_1_1websocket_1_1_connection.html',1,'crow::websocket']]], + ['context_46',['context',['../structcrow_1_1_cookie_parser_1_1context.html',1,'crow::CookieParser::context'],['../structcrow_1_1_c_o_r_s_handler_1_1context.html',1,'crow::CORSHandler::context'],['../structcrow_1_1detail_1_1context.html',1,'crow::detail::context< Middlewares >'],['../structcrow_1_1_session_middleware_1_1context.html',1,'crow::SessionMiddleware< Store >::context'],['../structcrow_1_1_u_t_f8_1_1context.html',1,'crow::UTF8::context']]], + ['context_3c_20middlewares_2e_2e_2e_20_3e_47',['context< Middlewares... >',['../structcrow_1_1detail_1_1context.html',1,'crow::detail']]], + ['cookie_48',['Cookie',['../structcrow_1_1_cookie_parser_1_1_cookie.html',1,'crow::CookieParser']]], + ['cookieparser_49',['CookieParser',['../structcrow_1_1_cookie_parser.html',1,'crow']]], + ['corshandler_50',['CORSHandler',['../structcrow_1_1_c_o_r_s_handler.html',1,'crow']]], + ['corsrules_51',['CORSRules',['../structcrow_1_1_c_o_r_s_rules.html',1,'crow']]], + ['crow_52',['crow',['../namespacecrow.html',1,'']]], + ['crow_53',['Crow',['../classcrow_1_1_crow.html#abb69a7bf5d4a791a398c838d37086d94',1,'crow::Crow::Crow()'],['../classcrow_1_1_crow.html',1,'crow::Crow< Middlewares >']]], + ['crow_5fbp_5fcatchall_5froute_54',['CROW_BP_CATCHALL_ROUTE',['../app_8h.html#a8490c9a408955fcdb2237c694427754b',1,'app.h']]], + ['crow_5fbp_5froute_55',['CROW_BP_ROUTE',['../app_8h.html#a479d0a674825fb289848dad80379efc7',1,'app.h']]], + ['crow_5fcatchall_5froute_56',['CROW_CATCHALL_ROUTE',['../app_8h.html#a182dcf033f11eb89855a7b98bd6cfe02',1,'app.h']]], + ['crow_5fmiddlewares_57',['CROW_MIDDLEWARES',['../app_8h.html#a12ac01cb1979c953ac1c1203114c5e0e',1,'app.h']]], + ['crow_5froute_58',['CROW_ROUTE',['../app_8h.html#a6aa7ec3a2f3ee3f17d5f9acd879e7381',1,'app.h']]], + ['crow_5fwebsocket_5froute_59',['CROW_WEBSOCKET_ROUTE',['../app_8h.html#a8deb011ba0eae4684d6c6bb13014c926',1,'app.h']]], + ['multipart_60',['multipart',['../namespacecrow_1_1multipart.html',1,'crow']]], + ['websocket_61',['websocket',['../namespacecrow_1_1websocket.html',1,'crow']]] +]; diff --git a/1.2/reference/search/all_3.html b/1.2/reference/search/all_3.html new file mode 100644 index 000000000..39767b85b --- /dev/null +++ b/1.2/reference/search/all_3.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_3.js b/1.2/reference/search/all_3.js new file mode 100644 index 000000000..a8a32fd94 --- /dev/null +++ b/1.2/reference/search/all_3.js @@ -0,0 +1,11 @@ +var searchData= +[ + ['d_62',['d',['../classcrow_1_1json_1_1rvalue.html#a4a3e33d65b812ed583814a7ac2e1f448',1,'crow::json::rvalue']]], + ['data_63',['data',['../structcrow_1_1http__parser.html#ac110503546750f343ad176dea0f48aa0',1,'crow::http_parser']]], + ['debug_5fprint_64',['debug_print',['../classcrow_1_1_crow.html#a839c1e6f82d577308eb6f0d4948a4fbb',1,'crow::Crow']]], + ['dispatch_65',['dispatch',['../structcrow_1_1request.html#ac3e72e3fe415c68618dee999e3984160',1,'crow::request::dispatch()'],['../classcrow_1_1websocket_1_1_connection.html#a0d7758d7d22d74ee9ed17c8c7df0a380',1,'crow::websocket::Connection::dispatch(CompletionHandler &&handler)']]], + ['do_5fread_66',['do_read',['../classcrow_1_1websocket_1_1_connection.html#a1049d7689f068379e98954bfb04bee5c',1,'crow::websocket::Connection']]], + ['do_5fwrite_67',['do_write',['../classcrow_1_1websocket_1_1_connection.html#a787dde96965bf30d994bbc5fb3388281',1,'crow::websocket::Connection']]], + ['dump_68',['dump',['../structcrow_1_1multipart_1_1message.html#adac4c7af1a5d0eb66c2accbaf80e0196',1,'crow::multipart::message::dump() const override'],['../structcrow_1_1multipart_1_1message.html#abeeebf36687f9cbdf06a6521eac1ce33',1,'crow::multipart::message::dump(int part_) const']]], + ['dynamicrule_69',['DynamicRule',['../classcrow_1_1_dynamic_rule.html',1,'crow']]] +]; diff --git a/1.2/reference/search/all_4.html b/1.2/reference/search/all_4.html new file mode 100644 index 000000000..fc40463c8 --- /dev/null +++ b/1.2/reference/search/all_4.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_4.js b/1.2/reference/search/all_4.js new file mode 100644 index 000000000..e8d488abc --- /dev/null +++ b/1.2/reference/search/all_4.js @@ -0,0 +1,9 @@ +var searchData= +[ + ['e_5f_70',['e_',['../structcrow_1_1json_1_1detail_1_1r__string.html#adeb368c4c0dfeb349bb32129e8dee23b',1,'crow::json::detail::r_string']]], + ['empty_5fobject_71',['empty_object',['../classcrow_1_1json_1_1wvalue.html#a8875c69038bd1a9c23485f099e471b96',1,'crow::json::wvalue']]], + ['end_72',['end',['../structcrow_1_1response.html#abef42200eca49c70dc1f5140ee3603ab',1,'crow::response::end()'],['../structcrow_1_1response.html#a10da2e17421586b68f27ef1533ec677b',1,'crow::response::end(const std::string &body_part)']]], + ['estimate_5flength_73',['estimate_length',['../classcrow_1_1json_1_1wvalue.html#a5af23d208ed3d066a0fb5339350978c6',1,'crow::json::wvalue']]], + ['exception_5fhandler_74',['exception_handler',['../classcrow_1_1_crow.html#a872d39321015ac4f48ec8a6659dda99b',1,'crow::Crow']]], + ['expirationtracker_75',['ExpirationTracker',['../structcrow_1_1session_1_1_expiration_tracker.html',1,'crow::session']]] +]; diff --git a/1.2/reference/search/all_5.html b/1.2/reference/search/all_5.html new file mode 100644 index 000000000..9dd9344b0 --- /dev/null +++ b/1.2/reference/search/all_5.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_5.js b/1.2/reference/search/all_5.js new file mode 100644 index 000000000..c558751c9 --- /dev/null +++ b/1.2/reference/search/all_5.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['feed_76',['feed',['../structcrow_1_1_h_t_t_p_parser.html#a9ca5bdc64f7ce0ffa836c6263da0da45',1,'crow::HTTPParser']]], + ['filestore_77',['FileStore',['../structcrow_1_1_file_store.html',1,'crow']]], + ['flags_78',['flags',['../structcrow_1_1http__parser.html#ab05c7677ce9af6c659e4401bb24484e7',1,'crow::http_parser']]] +]; diff --git a/1.2/reference/search/all_6.html b/1.2/reference/search/all_6.html new file mode 100644 index 000000000..f1e516d75 --- /dev/null +++ b/1.2/reference/search/all_6.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_6.js b/1.2/reference/search/all_6.js new file mode 100644 index 000000000..52a5c389b --- /dev/null +++ b/1.2/reference/search/all_6.js @@ -0,0 +1,13 @@ +var searchData= +[ + ['get_79',['get',['../structcrow_1_1detail_1_1check__after__handle__arity__3_1_1get.html',1,'crow::detail::check_after_handle_arity_3< MW >::get< T, >'],['../structcrow_1_1detail_1_1check__after__handle__arity__3__const_1_1get.html',1,'crow::detail::check_after_handle_arity_3_const< MW >::get< T, const >'],['../structcrow_1_1detail_1_1check__before__handle__arity__3_1_1get.html',1,'crow::detail::check_before_handle_arity_3< MW >::get< T, >'],['../structcrow_1_1detail_1_1check__before__handle__arity__3__const_1_1get.html',1,'crow::detail::check_before_handle_arity_3_const< MW >::get< T, const >'],['../structcrow_1_1detail_1_1check__global__call__false_1_1get.html',1,'crow::detail::check_global_call_false< MW >::get< T, type >'],['../classcrow_1_1query__string.html#a7db05380bed403b88cb2fe6a5fdd8d75',1,'crow::query_string::get()']]], + ['get_5fbody_5fparams_80',['get_body_params',['../structcrow_1_1request.html#af2679155b496b7d8d80a82c0d9a175b5',1,'crow::request']]], + ['get_5fdefault_5ftimeout_81',['get_default_timeout',['../classcrow_1_1detail_1_1task__timer.html#ae11e1259251e562ea3be457457b3b287',1,'crow::detail::task_timer']]], + ['get_5fdict_82',['get_dict',['../classcrow_1_1query__string.html#af56add12ca6a7f0222956e353d1d40bb',1,'crow::query_string']]], + ['get_5ferror_83',['get_error',['../classcrow_1_1_router.html#a39beca1acc1997c68db0d34556b6cf87',1,'crow::Router']]], + ['get_5fheader_5fobject_84',['get_header_object',['../namespacecrow_1_1multipart.html#acecc1d3d17777095c4439ce5159f035d',1,'crow::multipart']]], + ['get_5fheader_5fvalue_85',['get_header_value',['../namespacecrow.html#ac0940ae1e094df6107d3a2604537279a',1,'crow']]], + ['get_5fheader_5fvalue_5fobject_86',['get_header_value_object',['../namespacecrow_1_1multipart.html#adb2a619f5ebb5d00a19d3e96dc3b0433',1,'crow::multipart']]], + ['get_5flist_87',['get_list',['../classcrow_1_1query__string.html#a657e5fe435375cd31229944ed2ad5608',1,'crow::query_string']]], + ['global_88',['global',['../structcrow_1_1_c_o_r_s_rules.html#a1684428b8d96050e7dbb852b526ec5a2',1,'crow::CORSRules::global()'],['../structcrow_1_1_c_o_r_s_handler.html#a969edd2b3d6768d067147839a430a976',1,'crow::CORSHandler::global()']]] +]; diff --git a/1.2/reference/search/all_7.html b/1.2/reference/search/all_7.html new file mode 100644 index 000000000..8ddbf6c8e --- /dev/null +++ b/1.2/reference/search/all_7.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_7.js b/1.2/reference/search/all_7.js new file mode 100644 index 000000000..94d6a23f5 --- /dev/null +++ b/1.2/reference/search/all_7.js @@ -0,0 +1,20 @@ +var searchData= +[ + ['handle_89',['handle',['../classcrow_1_1_crow.html#a866cb219bb77c19326f39f431424e1c7',1,'crow::Crow']]], + ['handle_5ffragment_90',['handle_fragment',['../classcrow_1_1websocket_1_1_connection.html#a292002f44552e5eabd8dd65f476a4c28',1,'crow::websocket::Connection']]], + ['handle_5ffull_91',['handle_full',['../classcrow_1_1_crow.html#accf00be55c273297b758fa243f107018',1,'crow::Crow']]], + ['handle_5finitial_92',['handle_initial',['../classcrow_1_1_crow.html#a761ebd8c33ae35a3c61c7a160ad40789',1,'crow::Crow']]], + ['handle_5fupgrade_93',['handle_upgrade',['../classcrow_1_1_crow.html#a6e435bf5275735effd32647772bdbd04',1,'crow::Crow']]], + ['handler_5ftype_5fhelper_94',['handler_type_helper',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html',1,'crow::detail::routing_handler_call_helper::Wrapped']]], + ['handler_5ftype_5fhelper_3c_20argswrapped_2e_2e_2e_20_3e_95',['handler_type_helper< ArgsWrapped... >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html',1,'crow::detail::routing_handler_call_helper::Wrapped']]], + ['handler_5ftype_5fhelper_3c_20const_20request_20_26_2c_20args_2e_2e_2e_20_3e_96',['handler_type_helper< const request &, Args... >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.html',1,'crow::detail::routing_handler_call_helper::Wrapped']]], + ['handler_5ftype_5fhelper_3c_20const_20request_20_26_2c_20response_20_26_2c_20args_2e_2e_2e_20_3e_97',['handler_type_helper< const request &, response &, Args... >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.html',1,'crow::detail::routing_handler_call_helper::Wrapped']]], + ['has_98',['has',['../classcrow_1_1json_1_1rvalue.html#a48ac4fff801f365fb2b82f1ed7ebe983',1,'crow::json::rvalue']]], + ['header_99',['header',['../structcrow_1_1multipart_1_1header.html',1,'crow::multipart']]], + ['headers_100',['headers',['../structcrow_1_1response.html#ae56cfc39f24a56748c11016842427fb3',1,'crow::response::headers()'],['../structcrow_1_1multipart_1_1part.html#a8ff7f3aac814d93500d475da150fcbc6',1,'crow::multipart::part::headers()'],['../structcrow_1_1multipart_1_1message.html#ae333adda5d66d21018a978e6a3c317dd',1,'crow::multipart::message::headers()'],['../structcrow_1_1_c_o_r_s_rules.html#aef945727e83b664728033243b2dd4977',1,'crow::CORSRules::headers(const std::string &header)'],['../structcrow_1_1_c_o_r_s_rules.html#acd966b06be1d0a8077cb4ead3defa2dd',1,'crow::CORSRules::headers(const std::string &header, Headers... header_list)']]], + ['http_5fmajor_101',['http_major',['../structcrow_1_1http__parser.html#a6f9afc90d7c8557570973524e41fc299',1,'crow::http_parser']]], + ['http_5fparser_102',['http_parser',['../structcrow_1_1http__parser.html',1,'crow']]], + ['http_5fparser_5fsettings_103',['http_parser_settings',['../structcrow_1_1http__parser__settings.html',1,'crow']]], + ['httpparser_104',['HTTPParser',['../structcrow_1_1_h_t_t_p_parser.html',1,'crow']]], + ['httpparser_3c_20crow_3a_3aconnection_20_3e_105',['HTTPParser< crow::Connection >',['../structcrow_1_1_h_t_t_p_parser.html',1,'crow']]] +]; diff --git a/1.2/reference/search/all_8.html b/1.2/reference/search/all_8.html new file mode 100644 index 000000000..83c55ae22 --- /dev/null +++ b/1.2/reference/search/all_8.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_8.js b/1.2/reference/search/all_8.js new file mode 100644 index 000000000..618c615db --- /dev/null +++ b/1.2/reference/search/all_8.js @@ -0,0 +1,17 @@ +var searchData= +[ + ['i_106',['i',['../classcrow_1_1json_1_1rvalue.html#a1a9a1a3616d6484bf3dcdb941cf8e6da',1,'crow::json::rvalue']]], + ['ignore_107',['ignore',['../structcrow_1_1_c_o_r_s_rules.html#af7c411616ad51fb531a6ef0e0de4efe2',1,'crow::CORSRules']]], + ['ilocalmiddleware_108',['ILocalMiddleware',['../structcrow_1_1_i_local_middleware.html',1,'crow']]], + ['iloghandler_109',['ILogHandler',['../classcrow_1_1_i_log_handler.html',1,'crow']]], + ['inmemorystore_110',['InMemoryStore',['../structcrow_1_1_in_memory_store.html',1,'crow']]], + ['invalid_5ftemplate_5fexception_111',['invalid_template_exception',['../classcrow_1_1mustache_1_1invalid__template__exception.html',1,'crow::mustache']]], + ['is_5fafter_5fhandle_5farity_5f3_5fimpl_112',['is_after_handle_arity_3_impl',['../structcrow_1_1detail_1_1is__after__handle__arity__3__impl.html',1,'crow::detail']]], + ['is_5falive_113',['is_alive',['../structcrow_1_1response.html#ac29da52ee1e0b55086cd8eedd6c22da1',1,'crow::response']]], + ['is_5fbefore_5fhandle_5farity_5f3_5fimpl_114',['is_before_handle_arity_3_impl',['../structcrow_1_1detail_1_1is__before__handle__arity__3__impl.html',1,'crow::detail']]], + ['is_5fcompleted_115',['is_completed',['../structcrow_1_1response.html#a9fb82c40e0c0844db70b7b86b4a23e9f',1,'crow::response']]], + ['is_5fempty_116',['is_empty',['../classcrow_1_1_trie.html#af2cada415bae6140779323f453a5a146',1,'crow::Trie']]], + ['is_5ffin_117',['is_FIN',['../classcrow_1_1websocket_1_1_connection.html#a98f4af4eac4b807f970667b0147869a4',1,'crow::websocket::Connection']]], + ['is_5fmiddleware_5fglobal_118',['is_middleware_global',['../structcrow_1_1detail_1_1is__middleware__global.html',1,'crow::detail']]], + ['is_5fstatic_5ftype_119',['is_static_type',['../structcrow_1_1response.html#aff527a091cf5054e933a244b078648c1',1,'crow::response']]] +]; diff --git a/1.2/reference/search/all_9.html b/1.2/reference/search/all_9.html new file mode 100644 index 000000000..1e263c134 --- /dev/null +++ b/1.2/reference/search/all_9.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_9.js b/1.2/reference/search/all_9.js new file mode 100644 index 000000000..049637e07 --- /dev/null +++ b/1.2/reference/search/all_9.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['keep_5falive_120',['keep_alive',['../structcrow_1_1request.html#a5148ce95969d261e50ee977c1dc7960c',1,'crow::request']]] +]; diff --git a/1.2/reference/search/all_a.html b/1.2/reference/search/all_a.html new file mode 100644 index 000000000..3a6cac108 --- /dev/null +++ b/1.2/reference/search/all_a.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_a.js b/1.2/reference/search/all_a.js new file mode 100644 index 000000000..6f9cdf2fe --- /dev/null +++ b/1.2/reference/search/all_a.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['lo_121',['lo',['../classcrow_1_1json_1_1rvalue.html#a2b938dacf1809bb38add4ac8bbeb46ed',1,'crow::json::rvalue']]], + ['logger_122',['logger',['../classcrow_1_1logger.html',1,'crow']]], + ['loglevel_123',['loglevel',['../classcrow_1_1_crow.html#a7b6c225d3bba772eeadad89ebde68d21',1,'crow::Crow']]] +]; diff --git a/1.2/reference/search/all_b.html b/1.2/reference/search/all_b.html new file mode 100644 index 000000000..130deb4ed --- /dev/null +++ b/1.2/reference/search/all_b.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_b.js b/1.2/reference/search/all_b.js new file mode 100644 index 000000000..9a92eb149 --- /dev/null +++ b/1.2/reference/search/all_b.js @@ -0,0 +1,20 @@ +var searchData= +[ + ['manual_5flength_5fheader_124',['manual_length_header',['../structcrow_1_1response.html#a95f300c05782e1934dad522b6d6588cf',1,'crow::response']]], + ['max_5fage_125',['max_age',['../structcrow_1_1_c_o_r_s_rules.html#aa3721c183750d7317d165c1b89013717',1,'crow::CORSRules']]], + ['max_5fpayload_126',['max_payload',['../classcrow_1_1_web_socket_rule.html#ad4d8b25025e767fbe9af7f7c4263c2cb',1,'crow::WebSocketRule']]], + ['message_127',['message',['../structcrow_1_1multipart_1_1message.html',1,'crow::multipart::message'],['../structcrow_1_1multipart_1_1message.html#a32946a0f39a8d024aaf4643116a7561b',1,'crow::multipart::message::message(const request &req)'],['../structcrow_1_1multipart_1_1message.html#a0007fa0cadffae1a8d16fac169d1527b',1,'crow::multipart::message::message(const ci_map &headers, const std::string &boundary, const std::vector< part > &sections)']]], + ['methods_128',['methods',['../structcrow_1_1_c_o_r_s_rules.html#a7ffe0b716c19efe9f576091c92cf83b4',1,'crow::CORSRules::methods(crow::HTTPMethod method, Methods... method_list)'],['../structcrow_1_1_c_o_r_s_rules.html#a345cef92c2f28444e505646d429717cb',1,'crow::CORSRules::methods(crow::HTTPMethod method)']]], + ['middleware_5fcall_5fcriteria_5fdynamic_129',['middleware_call_criteria_dynamic',['../structcrow_1_1detail_1_1middleware__call__criteria__dynamic.html',1,'crow::detail']]], + ['middleware_5fcall_5fcriteria_5fdynamic_3c_20false_20_3e_130',['middleware_call_criteria_dynamic< false >',['../structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.html',1,'crow::detail']]], + ['middleware_5fcall_5fcriteria_5fdynamic_3c_20true_20_3e_131',['middleware_call_criteria_dynamic< true >',['../structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.html',1,'crow::detail']]], + ['middleware_5fcall_5fcriteria_5fonly_5fglobal_132',['middleware_call_criteria_only_global',['../structcrow_1_1detail_1_1middleware__call__criteria__only__global.html',1,'crow::detail']]], + ['middleware_5findices_133',['middleware_indices',['../structcrow_1_1detail_1_1middleware__indices.html',1,'crow::detail']]], + ['middlewares_134',['middlewares',['../structcrow_1_1_rule_parameter_traits.html#a137eb67383f095ce7ae5ef4da19656ab',1,'crow::RuleParameterTraits']]], + ['moved_135',['moved',['../structcrow_1_1response.html#a760bca5f5fdee03518d59d9538ce5432',1,'crow::response']]], + ['moved_5fperm_136',['moved_perm',['../structcrow_1_1response.html#a9ee58f8b775b2566418b298fe33c0dcc',1,'crow::response']]], + ['mp_5fmap_137',['mp_map',['../namespacecrow_1_1multipart.html#a071bb6d802c0edd823147fa6acaebb2b',1,'crow::multipart']]], + ['mph_5fmap_138',['mph_map',['../namespacecrow_1_1multipart.html#a6a2722b508669592976047a34d6eba0c',1,'crow::multipart']]], + ['multi_5fvalue_139',['multi_value',['../structcrow_1_1session_1_1multi__value.html',1,'crow::session']]], + ['multithreaded_140',['multithreaded',['../classcrow_1_1_crow.html#a0149b20b7f6c0123292286f54638d456',1,'crow::Crow']]] +]; diff --git a/1.2/reference/search/all_c.html b/1.2/reference/search/all_c.html new file mode 100644 index 000000000..3dd5af06d --- /dev/null +++ b/1.2/reference/search/all_c.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_c.js b/1.2/reference/search/all_c.js new file mode 100644 index 000000000..4875c4ff2 --- /dev/null +++ b/1.2/reference/search/all_c.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['node_141',['Node',['../structcrow_1_1_trie_1_1_node.html',1,'crow::Trie']]], + ['nt_142',['nt',['../classcrow_1_1json_1_1rvalue.html#a9bf75ffd4603990be7d0eaa192ac54fb',1,'crow::json::rvalue']]] +]; diff --git a/1.2/reference/search/all_d.html b/1.2/reference/search/all_d.html new file mode 100644 index 000000000..af7f2f0f5 --- /dev/null +++ b/1.2/reference/search/all_d.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_d.js b/1.2/reference/search/all_d.js new file mode 100644 index 000000000..7d2fc035f --- /dev/null +++ b/1.2/reference/search/all_d.js @@ -0,0 +1,8 @@ +var searchData= +[ + ['opcode_143',['opcode',['../classcrow_1_1websocket_1_1_connection.html#a6d74305323202dc7ebd07cbd3ee19f98',1,'crow::websocket::Connection']]], + ['operator_20double_144',['operator double',['../structcrow_1_1multipart_1_1header.html#a0b87278e0ebe8d323f46c9ed64fc385a',1,'crow::multipart::header::operator double()'],['../structcrow_1_1multipart_1_1part.html#ac9c4ebeeabe158725bc67cf14c9f957e',1,'crow::multipart::part::operator double()']]], + ['operator_20int_145',['operator int',['../structcrow_1_1multipart_1_1header.html#adff380493f414108eb67420d06d426ee',1,'crow::multipart::header::operator int()'],['../structcrow_1_1multipart_1_1part.html#a06851f0fd2d36b71139e8488fb646b7e',1,'crow::multipart::part::operator int()']]], + ['origin_146',['origin',['../structcrow_1_1_c_o_r_s_rules.html#a1d7a6517c7c256046065b2a02a25f6fa',1,'crow::CORSRules']]], + ['string_147',['string',['../classcrow_1_1json_1_1rvalue.html#a2d5dd8607112a132fe070dee432987ae',1,'crow::json::rvalue']]] +]; diff --git a/1.2/reference/search/all_e.html b/1.2/reference/search/all_e.html new file mode 100644 index 000000000..e25df423a --- /dev/null +++ b/1.2/reference/search/all_e.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_e.js b/1.2/reference/search/all_e.js new file mode 100644 index 000000000..a2369889d --- /dev/null +++ b/1.2/reference/search/all_e.js @@ -0,0 +1,17 @@ +var searchData= +[ + ['params_148',['params',['../structcrow_1_1multipart_1_1header.html#a18422d09aac9c5d5751799862d41a73c',1,'crow::multipart::header']]], + ['part_149',['part',['../structcrow_1_1multipart_1_1part.html',1,'crow::multipart']]], + ['part_5fmap_150',['part_map',['../structcrow_1_1multipart_1_1message.html#a76d89e2bff4c90307053bcb895d334ec',1,'crow::multipart::message']]], + ['partial_5fcontext_151',['partial_context',['../structcrow_1_1detail_1_1partial__context.html',1,'crow::detail']]], + ['partial_5fcontext_3c_20middlewares_2e_2e_2e_20_3e_152',['partial_context< Middlewares... >',['../structcrow_1_1detail_1_1partial__context.html',1,'crow::detail']]], + ['partial_5fcontext_3c_3e_153',['partial_context<>',['../structcrow_1_1detail_1_1partial__context_3_4.html',1,'crow::detail']]], + ['parts_154',['parts',['../structcrow_1_1multipart_1_1message.html#a05e9cf3feb60f4534af334b2dd5eadf2',1,'crow::multipart::message']]], + ['peek_5ffirst_155',['peek_first',['../structcrow_1_1session_1_1_expiration_tracker.html#a3a41ed909b0162aaf0ba02725e468951',1,'crow::session::ExpirationTracker']]], + ['pop_156',['pop',['../classcrow_1_1query__string.html#ab0a81b08a5531b98c08b1a6a268ebea1',1,'crow::query_string']]], + ['pop_5fdict_157',['pop_dict',['../classcrow_1_1query__string.html#a0744b06ff0709ebbe7c2a1646564508b',1,'crow::query_string']]], + ['pop_5flist_158',['pop_list',['../classcrow_1_1query__string.html#a8ef1a91122dc53e1235919e107fd1a9c',1,'crow::query_string']]], + ['port_159',['port',['../classcrow_1_1_crow.html#a365f9c95fc2bd8bb583967f499c1f4a1',1,'crow::Crow::port(std::uint16_t port)'],['../classcrow_1_1_crow.html#a87d0e10ed791c6847d8b7dfff2369aae',1,'crow::Crow::port()']]], + ['post_160',['post',['../structcrow_1_1request.html#a33aa146a3914864ce82ef22136451601',1,'crow::request::post()'],['../classcrow_1_1websocket_1_1_connection.html#ae55db4104d46350f5a9e040d32600984',1,'crow::websocket::Connection::post()']]], + ['prefix_161',['prefix',['../structcrow_1_1_c_o_r_s_rules.html#a98b09d1b3ebcc8db99a845333dc1ffff',1,'crow::CORSRules::prefix()'],['../structcrow_1_1_c_o_r_s_handler.html#a2805b07fdc18c36a89d5ad3886c3a5f5',1,'crow::CORSHandler::prefix()']]] +]; diff --git a/1.2/reference/search/all_f.html b/1.2/reference/search/all_f.html new file mode 100644 index 000000000..b23da6ce4 --- /dev/null +++ b/1.2/reference/search/all_f.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/all_f.js b/1.2/reference/search/all_f.js new file mode 100644 index 000000000..b3491987a --- /dev/null +++ b/1.2/reference/search/all_f.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['query_5fstring_162',['query_string',['../classcrow_1_1query__string.html',1,'crow']]] +]; diff --git a/1.2/reference/search/classes_0.html b/1.2/reference/search/classes_0.html new file mode 100644 index 000000000..af8159ee6 --- /dev/null +++ b/1.2/reference/search/classes_0.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_0.js b/1.2/reference/search/classes_0.js new file mode 100644 index 000000000..989c3ad93 --- /dev/null +++ b/1.2/reference/search/classes_0.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['action_243',['Action',['../structcrow_1_1mustache_1_1_action.html',1,'crow::mustache']]] +]; diff --git a/1.2/reference/search/classes_1.html b/1.2/reference/search/classes_1.html new file mode 100644 index 000000000..576e91689 --- /dev/null +++ b/1.2/reference/search/classes_1.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_1.js b/1.2/reference/search/classes_1.js new file mode 100644 index 000000000..159066890 --- /dev/null +++ b/1.2/reference/search/classes_1.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['baserule_244',['BaseRule',['../classcrow_1_1_base_rule.html',1,'crow']]], + ['blueprint_245',['Blueprint',['../classcrow_1_1_blueprint.html',1,'crow']]] +]; diff --git a/1.2/reference/search/classes_10.html b/1.2/reference/search/classes_10.html new file mode 100644 index 000000000..4af2c805a --- /dev/null +++ b/1.2/reference/search/classes_10.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_10.js b/1.2/reference/search/classes_10.js new file mode 100644 index 000000000..ffeb19c79 --- /dev/null +++ b/1.2/reference/search/classes_10.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['taggedrule_327',['TaggedRule',['../classcrow_1_1_tagged_rule.html',1,'crow']]], + ['task_5ftimer_328',['task_timer',['../classcrow_1_1detail_1_1task__timer.html',1,'crow::detail']]], + ['template_5ft_329',['template_t',['../classcrow_1_1mustache_1_1template__t.html',1,'crow::mustache']]], + ['trie_330',['Trie',['../classcrow_1_1_trie.html',1,'crow']]] +]; diff --git a/1.2/reference/search/classes_11.html b/1.2/reference/search/classes_11.html new file mode 100644 index 000000000..ed167c849 --- /dev/null +++ b/1.2/reference/search/classes_11.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_11.js b/1.2/reference/search/classes_11.js new file mode 100644 index 000000000..0645cf5a7 --- /dev/null +++ b/1.2/reference/search/classes_11.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['utf8_331',['UTF8',['../structcrow_1_1_u_t_f8.html',1,'crow']]] +]; diff --git a/1.2/reference/search/classes_12.html b/1.2/reference/search/classes_12.html new file mode 100644 index 000000000..90bc9f579 --- /dev/null +++ b/1.2/reference/search/classes_12.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_12.js b/1.2/reference/search/classes_12.js new file mode 100644 index 000000000..3207c062f --- /dev/null +++ b/1.2/reference/search/classes_12.js @@ -0,0 +1,8 @@ +var searchData= +[ + ['weakwrappedmessage_332',['WeakWrappedMessage',['../structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.html',1,'crow::websocket::Connection']]], + ['websocketrule_333',['WebSocketRule',['../classcrow_1_1_web_socket_rule.html',1,'crow']]], + ['wrapped_334',['Wrapped',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html',1,'crow::detail::routing_handler_call_helper']]], + ['wvalue_335',['wvalue',['../classcrow_1_1json_1_1wvalue.html',1,'crow::json']]], + ['wvalue_5freader_336',['wvalue_reader',['../structcrow_1_1json_1_1wvalue__reader.html',1,'crow::json']]] +]; diff --git a/1.2/reference/search/classes_2.html b/1.2/reference/search/classes_2.html new file mode 100644 index 000000000..956405e5a --- /dev/null +++ b/1.2/reference/search/classes_2.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_2.js b/1.2/reference/search/classes_2.js new file mode 100644 index 000000000..c82a4555b --- /dev/null +++ b/1.2/reference/search/classes_2.js @@ -0,0 +1,31 @@ +var searchData= +[ + ['cachedsession_246',['CachedSession',['../structcrow_1_1session_1_1_cached_session.html',1,'crow::session']]], + ['call_247',['call',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_3c_20f_2c_20nint_2c_20nuint_2c_20ndouble_2c_20nstring_2c_20black_5fmagic_3a_3as_3c_20double_2c_20args1_2e_2e_2e_20_3e_2c_20black_5fmagic_3a_3as_3c_20args2_2e_2e_2e_20_3e_20_3e_248',['call< F, NInt, NUint, NDouble, NString, black_magic::S< double, Args1... >, black_magic::S< Args2... > >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_3c_20f_2c_20nint_2c_20nuint_2c_20ndouble_2c_20nstring_2c_20black_5fmagic_3a_3as_3c_20int64_5ft_2c_20args1_2e_2e_2e_20_3e_2c_20black_5fmagic_3a_3as_3c_20args2_2e_2e_2e_20_3e_20_3e_249',['call< F, NInt, NUint, NDouble, NString, black_magic::S< int64_t, Args1... >, black_magic::S< Args2... > >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_3c_20f_2c_20nint_2c_20nuint_2c_20ndouble_2c_20nstring_2c_20black_5fmagic_3a_3as_3c_20std_3a_3astring_2c_20args1_2e_2e_2e_20_3e_2c_20black_5fmagic_3a_3as_3c_20args2_2e_2e_2e_20_3e_20_3e_250',['call< F, NInt, NUint, NDouble, NString, black_magic::S< std::string, Args1... >, black_magic::S< Args2... > >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_3c_20f_2c_20nint_2c_20nuint_2c_20ndouble_2c_20nstring_2c_20black_5fmagic_3a_3as_3c_20uint64_5ft_2c_20args1_2e_2e_2e_20_3e_2c_20black_5fmagic_3a_3as_3c_20args2_2e_2e_2e_20_3e_20_3e_251',['call< F, NInt, NUint, NDouble, NString, black_magic::S< uint64_t, Args1... >, black_magic::S< Args2... > >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_3c_20f_2c_20nint_2c_20nuint_2c_20ndouble_2c_20nstring_2c_20black_5fmagic_3a_3as_3c_3e_2c_20black_5fmagic_3a_3as_3c_20args1_2e_2e_2e_20_3e_20_3e_252',['call< F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S< Args1... > >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_5fpair_253',['call_pair',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.html',1,'crow::detail::routing_handler_call_helper']]], + ['call_5fparams_254',['call_params',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html',1,'crow::detail::routing_handler_call_helper']]], + ['catchallrule_255',['CatchallRule',['../classcrow_1_1_catchall_rule.html',1,'crow']]], + ['cerrloghandler_256',['CerrLogHandler',['../classcrow_1_1_cerr_log_handler.html',1,'crow']]], + ['check_5fafter_5fhandle_5farity_5f3_257',['check_after_handle_arity_3',['../structcrow_1_1detail_1_1check__after__handle__arity__3.html',1,'crow::detail']]], + ['check_5fafter_5fhandle_5farity_5f3_5fconst_258',['check_after_handle_arity_3_const',['../structcrow_1_1detail_1_1check__after__handle__arity__3__const.html',1,'crow::detail']]], + ['check_5fbefore_5fhandle_5farity_5f3_259',['check_before_handle_arity_3',['../structcrow_1_1detail_1_1check__before__handle__arity__3.html',1,'crow::detail']]], + ['check_5fbefore_5fhandle_5farity_5f3_5fconst_260',['check_before_handle_arity_3_const',['../structcrow_1_1detail_1_1check__before__handle__arity__3__const.html',1,'crow::detail']]], + ['check_5fglobal_5fcall_5ffalse_261',['check_global_call_false',['../structcrow_1_1detail_1_1check__global__call__false.html',1,'crow::detail']]], + ['ci_5fhash_262',['ci_hash',['../structcrow_1_1ci__hash.html',1,'crow']]], + ['ci_5fkey_5feq_263',['ci_key_eq',['../structcrow_1_1ci__key__eq.html',1,'crow']]], + ['connection_264',['Connection',['../classcrow_1_1_connection.html',1,'crow']]], + ['connection_265',['connection',['../structcrow_1_1websocket_1_1connection.html',1,'crow::websocket']]], + ['connection_266',['Connection',['../classcrow_1_1websocket_1_1_connection.html',1,'crow::websocket']]], + ['context_267',['context',['../structcrow_1_1_cookie_parser_1_1context.html',1,'crow::CookieParser::context'],['../structcrow_1_1_c_o_r_s_handler_1_1context.html',1,'crow::CORSHandler::context'],['../structcrow_1_1detail_1_1context.html',1,'crow::detail::context< Middlewares >'],['../structcrow_1_1_session_middleware_1_1context.html',1,'crow::SessionMiddleware< Store >::context'],['../structcrow_1_1_u_t_f8_1_1context.html',1,'crow::UTF8::context']]], + ['context_3c_20middlewares_2e_2e_2e_20_3e_268',['context< Middlewares... >',['../structcrow_1_1detail_1_1context.html',1,'crow::detail']]], + ['cookie_269',['Cookie',['../structcrow_1_1_cookie_parser_1_1_cookie.html',1,'crow::CookieParser']]], + ['cookieparser_270',['CookieParser',['../structcrow_1_1_cookie_parser.html',1,'crow']]], + ['corshandler_271',['CORSHandler',['../structcrow_1_1_c_o_r_s_handler.html',1,'crow']]], + ['corsrules_272',['CORSRules',['../structcrow_1_1_c_o_r_s_rules.html',1,'crow']]], + ['crow_273',['Crow',['../classcrow_1_1_crow.html',1,'crow']]] +]; diff --git a/1.2/reference/search/classes_3.html b/1.2/reference/search/classes_3.html new file mode 100644 index 000000000..d33343bc1 --- /dev/null +++ b/1.2/reference/search/classes_3.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_3.js b/1.2/reference/search/classes_3.js new file mode 100644 index 000000000..e7c8808d6 --- /dev/null +++ b/1.2/reference/search/classes_3.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['dynamicrule_274',['DynamicRule',['../classcrow_1_1_dynamic_rule.html',1,'crow']]] +]; diff --git a/1.2/reference/search/classes_4.html b/1.2/reference/search/classes_4.html new file mode 100644 index 000000000..8430b07fe --- /dev/null +++ b/1.2/reference/search/classes_4.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_4.js b/1.2/reference/search/classes_4.js new file mode 100644 index 000000000..5c2714a96 --- /dev/null +++ b/1.2/reference/search/classes_4.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['expirationtracker_275',['ExpirationTracker',['../structcrow_1_1session_1_1_expiration_tracker.html',1,'crow::session']]] +]; diff --git a/1.2/reference/search/classes_5.html b/1.2/reference/search/classes_5.html new file mode 100644 index 000000000..c2f1b767b --- /dev/null +++ b/1.2/reference/search/classes_5.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_5.js b/1.2/reference/search/classes_5.js new file mode 100644 index 000000000..110c36a70 --- /dev/null +++ b/1.2/reference/search/classes_5.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['filestore_276',['FileStore',['../structcrow_1_1_file_store.html',1,'crow']]] +]; diff --git a/1.2/reference/search/classes_6.html b/1.2/reference/search/classes_6.html new file mode 100644 index 000000000..e39847ce8 --- /dev/null +++ b/1.2/reference/search/classes_6.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_6.js b/1.2/reference/search/classes_6.js new file mode 100644 index 000000000..5b5c53397 --- /dev/null +++ b/1.2/reference/search/classes_6.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['get_277',['get',['../structcrow_1_1detail_1_1check__after__handle__arity__3_1_1get.html',1,'crow::detail::check_after_handle_arity_3< MW >::get< T, >'],['../structcrow_1_1detail_1_1check__after__handle__arity__3__const_1_1get.html',1,'crow::detail::check_after_handle_arity_3_const< MW >::get< T, const >'],['../structcrow_1_1detail_1_1check__before__handle__arity__3_1_1get.html',1,'crow::detail::check_before_handle_arity_3< MW >::get< T, >'],['../structcrow_1_1detail_1_1check__before__handle__arity__3__const_1_1get.html',1,'crow::detail::check_before_handle_arity_3_const< MW >::get< T, const >'],['../structcrow_1_1detail_1_1check__global__call__false_1_1get.html',1,'crow::detail::check_global_call_false< MW >::get< T, type >']]] +]; diff --git a/1.2/reference/search/classes_7.html b/1.2/reference/search/classes_7.html new file mode 100644 index 000000000..a2c4d1a39 --- /dev/null +++ b/1.2/reference/search/classes_7.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_7.js b/1.2/reference/search/classes_7.js new file mode 100644 index 000000000..20d26964f --- /dev/null +++ b/1.2/reference/search/classes_7.js @@ -0,0 +1,12 @@ +var searchData= +[ + ['handler_5ftype_5fhelper_278',['handler_type_helper',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html',1,'crow::detail::routing_handler_call_helper::Wrapped']]], + ['handler_5ftype_5fhelper_3c_20argswrapped_2e_2e_2e_20_3e_279',['handler_type_helper< ArgsWrapped... >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html',1,'crow::detail::routing_handler_call_helper::Wrapped']]], + ['handler_5ftype_5fhelper_3c_20const_20request_20_26_2c_20args_2e_2e_2e_20_3e_280',['handler_type_helper< const request &, Args... >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.html',1,'crow::detail::routing_handler_call_helper::Wrapped']]], + ['handler_5ftype_5fhelper_3c_20const_20request_20_26_2c_20response_20_26_2c_20args_2e_2e_2e_20_3e_281',['handler_type_helper< const request &, response &, Args... >',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.html',1,'crow::detail::routing_handler_call_helper::Wrapped']]], + ['header_282',['header',['../structcrow_1_1multipart_1_1header.html',1,'crow::multipart']]], + ['http_5fparser_283',['http_parser',['../structcrow_1_1http__parser.html',1,'crow']]], + ['http_5fparser_5fsettings_284',['http_parser_settings',['../structcrow_1_1http__parser__settings.html',1,'crow']]], + ['httpparser_285',['HTTPParser',['../structcrow_1_1_h_t_t_p_parser.html',1,'crow']]], + ['httpparser_3c_20crow_3a_3aconnection_20_3e_286',['HTTPParser< crow::Connection >',['../structcrow_1_1_h_t_t_p_parser.html',1,'crow']]] +]; diff --git a/1.2/reference/search/classes_8.html b/1.2/reference/search/classes_8.html new file mode 100644 index 000000000..17003e480 --- /dev/null +++ b/1.2/reference/search/classes_8.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_8.js b/1.2/reference/search/classes_8.js new file mode 100644 index 000000000..49815b2e1 --- /dev/null +++ b/1.2/reference/search/classes_8.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['ilocalmiddleware_287',['ILocalMiddleware',['../structcrow_1_1_i_local_middleware.html',1,'crow']]], + ['iloghandler_288',['ILogHandler',['../classcrow_1_1_i_log_handler.html',1,'crow']]], + ['inmemorystore_289',['InMemoryStore',['../structcrow_1_1_in_memory_store.html',1,'crow']]], + ['invalid_5ftemplate_5fexception_290',['invalid_template_exception',['../classcrow_1_1mustache_1_1invalid__template__exception.html',1,'crow::mustache']]], + ['is_5fafter_5fhandle_5farity_5f3_5fimpl_291',['is_after_handle_arity_3_impl',['../structcrow_1_1detail_1_1is__after__handle__arity__3__impl.html',1,'crow::detail']]], + ['is_5fbefore_5fhandle_5farity_5f3_5fimpl_292',['is_before_handle_arity_3_impl',['../structcrow_1_1detail_1_1is__before__handle__arity__3__impl.html',1,'crow::detail']]], + ['is_5fmiddleware_5fglobal_293',['is_middleware_global',['../structcrow_1_1detail_1_1is__middleware__global.html',1,'crow::detail']]] +]; diff --git a/1.2/reference/search/classes_9.html b/1.2/reference/search/classes_9.html new file mode 100644 index 000000000..b8afa8cba --- /dev/null +++ b/1.2/reference/search/classes_9.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_9.js b/1.2/reference/search/classes_9.js new file mode 100644 index 000000000..bad7e8145 --- /dev/null +++ b/1.2/reference/search/classes_9.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['logger_294',['logger',['../classcrow_1_1logger.html',1,'crow']]] +]; diff --git a/1.2/reference/search/classes_a.html b/1.2/reference/search/classes_a.html new file mode 100644 index 000000000..6788af270 --- /dev/null +++ b/1.2/reference/search/classes_a.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_a.js b/1.2/reference/search/classes_a.js new file mode 100644 index 000000000..6799c2bcd --- /dev/null +++ b/1.2/reference/search/classes_a.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['message_295',['message',['../structcrow_1_1multipart_1_1message.html',1,'crow::multipart']]], + ['middleware_5fcall_5fcriteria_5fdynamic_296',['middleware_call_criteria_dynamic',['../structcrow_1_1detail_1_1middleware__call__criteria__dynamic.html',1,'crow::detail']]], + ['middleware_5fcall_5fcriteria_5fdynamic_3c_20false_20_3e_297',['middleware_call_criteria_dynamic< false >',['../structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.html',1,'crow::detail']]], + ['middleware_5fcall_5fcriteria_5fdynamic_3c_20true_20_3e_298',['middleware_call_criteria_dynamic< true >',['../structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.html',1,'crow::detail']]], + ['middleware_5fcall_5fcriteria_5fonly_5fglobal_299',['middleware_call_criteria_only_global',['../structcrow_1_1detail_1_1middleware__call__criteria__only__global.html',1,'crow::detail']]], + ['middleware_5findices_300',['middleware_indices',['../structcrow_1_1detail_1_1middleware__indices.html',1,'crow::detail']]], + ['multi_5fvalue_301',['multi_value',['../structcrow_1_1session_1_1multi__value.html',1,'crow::session']]] +]; diff --git a/1.2/reference/search/classes_b.html b/1.2/reference/search/classes_b.html new file mode 100644 index 000000000..3fcb49858 --- /dev/null +++ b/1.2/reference/search/classes_b.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_b.js b/1.2/reference/search/classes_b.js new file mode 100644 index 000000000..40ae83d93 --- /dev/null +++ b/1.2/reference/search/classes_b.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['node_302',['Node',['../structcrow_1_1_trie_1_1_node.html',1,'crow::Trie']]] +]; diff --git a/1.2/reference/search/classes_c.html b/1.2/reference/search/classes_c.html new file mode 100644 index 000000000..2f7b1f3da --- /dev/null +++ b/1.2/reference/search/classes_c.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_c.js b/1.2/reference/search/classes_c.js new file mode 100644 index 000000000..7c2e52b1e --- /dev/null +++ b/1.2/reference/search/classes_c.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['part_303',['part',['../structcrow_1_1multipart_1_1part.html',1,'crow::multipart']]], + ['partial_5fcontext_304',['partial_context',['../structcrow_1_1detail_1_1partial__context.html',1,'crow::detail']]], + ['partial_5fcontext_3c_20middlewares_2e_2e_2e_20_3e_305',['partial_context< Middlewares... >',['../structcrow_1_1detail_1_1partial__context.html',1,'crow::detail']]], + ['partial_5fcontext_3c_3e_306',['partial_context<>',['../structcrow_1_1detail_1_1partial__context_3_4.html',1,'crow::detail']]] +]; diff --git a/1.2/reference/search/classes_d.html b/1.2/reference/search/classes_d.html new file mode 100644 index 000000000..f9011e70f --- /dev/null +++ b/1.2/reference/search/classes_d.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_d.js b/1.2/reference/search/classes_d.js new file mode 100644 index 000000000..a3f4109d5 --- /dev/null +++ b/1.2/reference/search/classes_d.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['query_5fstring_307',['query_string',['../classcrow_1_1query__string.html',1,'crow']]] +]; diff --git a/1.2/reference/search/classes_e.html b/1.2/reference/search/classes_e.html new file mode 100644 index 000000000..bb33dcfa5 --- /dev/null +++ b/1.2/reference/search/classes_e.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_e.js b/1.2/reference/search/classes_e.js new file mode 100644 index 000000000..92d6c0d25 --- /dev/null +++ b/1.2/reference/search/classes_e.js @@ -0,0 +1,15 @@ +var searchData= +[ + ['r_5fstring_308',['r_string',['../structcrow_1_1json_1_1detail_1_1r__string.html',1,'crow::json::detail']]], + ['rendered_5ftemplate_309',['rendered_template',['../structcrow_1_1mustache_1_1rendered__template.html',1,'crow::mustache']]], + ['req_5fhandler_5fwrapper_310',['req_handler_wrapper',['../structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.html',1,'crow::detail::routing_handler_call_helper::Wrapped']]], + ['request_311',['request',['../structcrow_1_1request.html',1,'crow']]], + ['response_312',['response',['../structcrow_1_1response.html',1,'crow']]], + ['returnable_313',['returnable',['../structcrow_1_1returnable.html',1,'crow']]], + ['router_314',['Router',['../classcrow_1_1_router.html',1,'crow']]], + ['routing_5fhandle_5fresult_315',['routing_handle_result',['../structcrow_1_1routing__handle__result.html',1,'crow']]], + ['ruleparametertraits_316',['RuleParameterTraits',['../structcrow_1_1_rule_parameter_traits.html',1,'crow']]], + ['ruleparametertraits_3c_20dynamicrule_20_3e_317',['RuleParameterTraits< DynamicRule >',['../structcrow_1_1_rule_parameter_traits.html',1,'crow']]], + ['ruleparametertraits_3c_20taggedrule_3c_20args_2e_2e_2e_20_3e_20_3e_318',['RuleParameterTraits< TaggedRule< Args... > >',['../structcrow_1_1_rule_parameter_traits.html',1,'crow']]], + ['rvalue_319',['rvalue',['../classcrow_1_1json_1_1rvalue.html',1,'crow::json']]] +]; diff --git a/1.2/reference/search/classes_f.html b/1.2/reference/search/classes_f.html new file mode 100644 index 000000000..d1b67daa6 --- /dev/null +++ b/1.2/reference/search/classes_f.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/classes_f.js b/1.2/reference/search/classes_f.js new file mode 100644 index 000000000..a124bb40f --- /dev/null +++ b/1.2/reference/search/classes_f.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['sendmessagetype_320',['SendMessageType',['../structcrow_1_1websocket_1_1_connection_1_1_send_message_type.html',1,'crow::websocket::Connection']]], + ['server_321',['Server',['../classcrow_1_1_server.html',1,'crow']]], + ['sessionmiddleware_322',['SessionMiddleware',['../structcrow_1_1_session_middleware.html',1,'crow']]], + ['sha1_323',['SHA1',['../classsha1_1_1_s_h_a1.html',1,'sha1']]], + ['socketadaptor_324',['SocketAdaptor',['../structcrow_1_1_socket_adaptor.html',1,'crow']]], + ['ssladaptor_325',['SSLAdaptor',['../structcrow_1_1_s_s_l_adaptor.html',1,'crow']]], + ['static_5ffile_5finfo_326',['static_file_info',['../structcrow_1_1response_1_1static__file__info.html',1,'crow::response']]] +]; diff --git a/1.2/reference/search/close.svg b/1.2/reference/search/close.svg new file mode 100644 index 000000000..a933eea1a --- /dev/null +++ b/1.2/reference/search/close.svg @@ -0,0 +1,31 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/1.2/reference/search/defines_0.html b/1.2/reference/search/defines_0.html new file mode 100644 index 000000000..15cc3de38 --- /dev/null +++ b/1.2/reference/search/defines_0.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/defines_0.js b/1.2/reference/search/defines_0.js new file mode 100644 index 000000000..3a76e0b49 --- /dev/null +++ b/1.2/reference/search/defines_0.js @@ -0,0 +1,9 @@ +var searchData= +[ + ['crow_5fbp_5fcatchall_5froute_487',['CROW_BP_CATCHALL_ROUTE',['../app_8h.html#a8490c9a408955fcdb2237c694427754b',1,'app.h']]], + ['crow_5fbp_5froute_488',['CROW_BP_ROUTE',['../app_8h.html#a479d0a674825fb289848dad80379efc7',1,'app.h']]], + ['crow_5fcatchall_5froute_489',['CROW_CATCHALL_ROUTE',['../app_8h.html#a182dcf033f11eb89855a7b98bd6cfe02',1,'app.h']]], + ['crow_5fmiddlewares_490',['CROW_MIDDLEWARES',['../app_8h.html#a12ac01cb1979c953ac1c1203114c5e0e',1,'app.h']]], + ['crow_5froute_491',['CROW_ROUTE',['../app_8h.html#a6aa7ec3a2f3ee3f17d5f9acd879e7381',1,'app.h']]], + ['crow_5fwebsocket_5froute_492',['CROW_WEBSOCKET_ROUTE',['../app_8h.html#a8deb011ba0eae4684d6c6bb13014c926',1,'app.h']]] +]; diff --git a/1.2/reference/search/files_0.html b/1.2/reference/search/files_0.html new file mode 100644 index 000000000..9498842a6 --- /dev/null +++ b/1.2/reference/search/files_0.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/files_0.js b/1.2/reference/search/files_0.js new file mode 100644 index 000000000..06f2bb44b --- /dev/null +++ b/1.2/reference/search/files_0.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['app_2eh_341',['app.h',['../app_8h.html',1,'']]] +]; diff --git a/1.2/reference/search/files_1.html b/1.2/reference/search/files_1.html new file mode 100644 index 000000000..7050ef48a --- /dev/null +++ b/1.2/reference/search/files_1.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/files_1.js b/1.2/reference/search/files_1.js new file mode 100644 index 000000000..18f99f7b9 --- /dev/null +++ b/1.2/reference/search/files_1.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['tinysha1_2ehpp_342',['TinySHA1.hpp',['../_tiny_s_h_a1_8hpp.html',1,'']]] +]; diff --git a/1.2/reference/search/functions_0.html b/1.2/reference/search/functions_0.html new file mode 100644 index 000000000..eb4c5014c --- /dev/null +++ b/1.2/reference/search/functions_0.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_0.js b/1.2/reference/search/functions_0.js new file mode 100644 index 000000000..988672179 --- /dev/null +++ b/1.2/reference/search/functions_0.js @@ -0,0 +1,8 @@ +var searchData= +[ + ['add_343',['add',['../structcrow_1_1session_1_1_expiration_tracker.html#a82f229b28c67ea4adfaae80db9628824',1,'crow::session::ExpirationTracker']]], + ['add_5fblueprint_344',['add_blueprint',['../classcrow_1_1_crow.html#af0d01b97da7d4d20844a80fd31b74f46',1,'crow::Crow']]], + ['add_5fheader_345',['add_header',['../structcrow_1_1response.html#a16d1a8bcec6460ba97f90b80881693b8',1,'crow::response']]], + ['add_5fstatic_5fdir_346',['add_static_dir',['../classcrow_1_1_crow.html#a3cbe89120e47d2bd3d05376b9129adfa',1,'crow::Crow']]], + ['allow_5fcredentials_347',['allow_credentials',['../structcrow_1_1_c_o_r_s_rules.html#abca9739b2819cb386123997aab7b0dec',1,'crow::CORSRules']]] +]; diff --git a/1.2/reference/search/functions_1.html b/1.2/reference/search/functions_1.html new file mode 100644 index 000000000..ef4088b89 --- /dev/null +++ b/1.2/reference/search/functions_1.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_1.js b/1.2/reference/search/functions_1.js new file mode 100644 index 000000000..7bd0503d3 --- /dev/null +++ b/1.2/reference/search/functions_1.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['b_348',['b',['../classcrow_1_1json_1_1rvalue.html#a61a5f98c6b0257d53c60a70eeff15490',1,'crow::json::rvalue']]], + ['bindaddr_349',['bindaddr',['../classcrow_1_1_crow.html#a75777f82b6519c86d71446eb9285d774',1,'crow::Crow::bindaddr(std::string bindaddr)'],['../classcrow_1_1_crow.html#a8c816534804e7bd351ca692005bf3343',1,'crow::Crow::bindaddr()']]], + ['blueprint_350',['blueprint',['../structcrow_1_1_c_o_r_s_rules.html#ac26c50868a334cdd3601c7cd2f2a5248',1,'crow::CORSRules::blueprint()'],['../structcrow_1_1_c_o_r_s_handler.html#a218d078e061f8d2ad4c16e7db6022cad',1,'crow::CORSHandler::blueprint()']]], + ['build_5fheader_351',['build_header',['../classcrow_1_1websocket_1_1_connection.html#a2fc995281b9452b56f743294baa7ed17',1,'crow::websocket::Connection']]] +]; diff --git a/1.2/reference/search/functions_10.html b/1.2/reference/search/functions_10.html new file mode 100644 index 000000000..1bdc12572 --- /dev/null +++ b/1.2/reference/search/functions_10.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_10.js b/1.2/reference/search/functions_10.js new file mode 100644 index 000000000..060d9196b --- /dev/null +++ b/1.2/reference/search/functions_10.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['t_446',['t',['../classcrow_1_1json_1_1rvalue.html#a9c9f7242e4164f4ed690e50e3cf5f4b1',1,'crow::json::rvalue']]], + ['tick_447',['tick',['../classcrow_1_1_crow.html#a068042431b0be5911ee1689a285f4693',1,'crow::Crow']]], + ['timeout_448',['timeout',['../classcrow_1_1_crow.html#a47ed9a118820f6e6ba0b2bc37f0997fb',1,'crow::Crow']]] +]; diff --git a/1.2/reference/search/functions_11.html b/1.2/reference/search/functions_11.html new file mode 100644 index 000000000..188076ef2 --- /dev/null +++ b/1.2/reference/search/functions_11.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_11.js b/1.2/reference/search/functions_11.js new file mode 100644 index 000000000..c72615391 --- /dev/null +++ b/1.2/reference/search/functions_11.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['u_449',['u',['../classcrow_1_1json_1_1rvalue.html#a775273fbbe868c7c8d3a71acdb9ee276',1,'crow::json::rvalue']]], + ['unescape_450',['unescape',['../classcrow_1_1json_1_1rvalue.html#a8c60e32c3e25b71c794cc79a4dea466c',1,'crow::json::rvalue']]] +]; diff --git a/1.2/reference/search/functions_12.html b/1.2/reference/search/functions_12.html new file mode 100644 index 000000000..eb29d8f9a --- /dev/null +++ b/1.2/reference/search/functions_12.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_12.js b/1.2/reference/search/functions_12.js new file mode 100644 index 000000000..95022bfe9 --- /dev/null +++ b/1.2/reference/search/functions_12.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['validate_451',['validate',['../classcrow_1_1_crow.html#ab9a22c981e0afec0d55ee234683a6d38',1,'crow::Crow']]] +]; diff --git a/1.2/reference/search/functions_13.html b/1.2/reference/search/functions_13.html new file mode 100644 index 000000000..3da2ea69c --- /dev/null +++ b/1.2/reference/search/functions_13.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_13.js b/1.2/reference/search/functions_13.js new file mode 100644 index 000000000..e8c258469 --- /dev/null +++ b/1.2/reference/search/functions_13.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['wait_5ffor_5fserver_5fstart_452',['wait_for_server_start',['../classcrow_1_1_crow.html#a5e39821ccc9cbf8c6400fd86fc406c21',1,'crow::Crow']]], + ['wait_5ffor_5fstart_453',['wait_for_start',['../classcrow_1_1_server.html#a0b63b4a3da3acbb2a1870db19279f580',1,'crow::Server']]], + ['websocket_5fmax_5fpayload_454',['websocket_max_payload',['../classcrow_1_1_crow.html#a30d9cbcaa6aa3c3e44a8a3c4479fd7cf',1,'crow::Crow::websocket_max_payload(uint64_t max_payload)'],['../classcrow_1_1_crow.html#a391a488c01ce53c0ccfd502c7ad15640',1,'crow::Crow::websocket_max_payload()']]], + ['wvalue_455',['wvalue',['../classcrow_1_1json_1_1wvalue.html#a1813a29de56af96789cc76b8cdb0dbbe',1,'crow::json::wvalue']]] +]; diff --git a/1.2/reference/search/functions_2.html b/1.2/reference/search/functions_2.html new file mode 100644 index 000000000..ca5aa10e6 --- /dev/null +++ b/1.2/reference/search/functions_2.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_2.js b/1.2/reference/search/functions_2.js new file mode 100644 index 000000000..ad30cdf91 --- /dev/null +++ b/1.2/reference/search/functions_2.js @@ -0,0 +1,11 @@ +var searchData= +[ + ['catchall_5froute_352',['catchall_route',['../classcrow_1_1_crow.html#ab1beefb0c6fc3c534160ba3bbc615069',1,'crow::Crow']]], + ['check_5fdestroy_353',['check_destroy',['../classcrow_1_1websocket_1_1_connection.html#a8030e7ca3e9ee5d07ccf7f8cb43fa317',1,'crow::websocket::Connection']]], + ['clear_354',['clear',['../classcrow_1_1json_1_1wvalue.html#af46596998d8e639a23b401e951297b63',1,'crow::json::wvalue']]], + ['close_355',['close',['../classcrow_1_1websocket_1_1_connection.html#a663d3f3917b8cc7f9b54e6c7dfc8d604',1,'crow::websocket::Connection']]], + ['complete_5frequest_356',['complete_request',['../classcrow_1_1_connection.html#aa40019a3731cc55174401e3b31602524',1,'crow::Connection']]], + ['concurrency_357',['concurrency',['../classcrow_1_1_crow.html#a41686e6025705c1ab379b5ec71bbf983',1,'crow::Crow::concurrency(std::uint16_t concurrency)'],['../classcrow_1_1_crow.html#abd824d73fdd02ba810b8dd37e2900240',1,'crow::Crow::concurrency()']]], + ['connection_358',['Connection',['../classcrow_1_1websocket_1_1_connection.html#ae13084d8ea772f54bf3397a9fab107d8',1,'crow::websocket::Connection']]], + ['crow_359',['Crow',['../classcrow_1_1_crow.html#abb69a7bf5d4a791a398c838d37086d94',1,'crow::Crow']]] +]; diff --git a/1.2/reference/search/functions_3.html b/1.2/reference/search/functions_3.html new file mode 100644 index 000000000..d79f55b8e --- /dev/null +++ b/1.2/reference/search/functions_3.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_3.js b/1.2/reference/search/functions_3.js new file mode 100644 index 000000000..e75227538 --- /dev/null +++ b/1.2/reference/search/functions_3.js @@ -0,0 +1,9 @@ +var searchData= +[ + ['d_360',['d',['../classcrow_1_1json_1_1rvalue.html#a4a3e33d65b812ed583814a7ac2e1f448',1,'crow::json::rvalue']]], + ['debug_5fprint_361',['debug_print',['../classcrow_1_1_crow.html#a839c1e6f82d577308eb6f0d4948a4fbb',1,'crow::Crow']]], + ['dispatch_362',['dispatch',['../structcrow_1_1request.html#ac3e72e3fe415c68618dee999e3984160',1,'crow::request::dispatch()'],['../classcrow_1_1websocket_1_1_connection.html#a0d7758d7d22d74ee9ed17c8c7df0a380',1,'crow::websocket::Connection::dispatch(CompletionHandler &&handler)']]], + ['do_5fread_363',['do_read',['../classcrow_1_1websocket_1_1_connection.html#a1049d7689f068379e98954bfb04bee5c',1,'crow::websocket::Connection']]], + ['do_5fwrite_364',['do_write',['../classcrow_1_1websocket_1_1_connection.html#a787dde96965bf30d994bbc5fb3388281',1,'crow::websocket::Connection']]], + ['dump_365',['dump',['../structcrow_1_1multipart_1_1message.html#adac4c7af1a5d0eb66c2accbaf80e0196',1,'crow::multipart::message::dump() const override'],['../structcrow_1_1multipart_1_1message.html#abeeebf36687f9cbdf06a6521eac1ce33',1,'crow::multipart::message::dump(int part_) const']]] +]; diff --git a/1.2/reference/search/functions_4.html b/1.2/reference/search/functions_4.html new file mode 100644 index 000000000..1657cad0d --- /dev/null +++ b/1.2/reference/search/functions_4.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_4.js b/1.2/reference/search/functions_4.js new file mode 100644 index 000000000..6ae535a33 --- /dev/null +++ b/1.2/reference/search/functions_4.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['empty_5fobject_366',['empty_object',['../classcrow_1_1json_1_1wvalue.html#a8875c69038bd1a9c23485f099e471b96',1,'crow::json::wvalue']]], + ['end_367',['end',['../structcrow_1_1response.html#abef42200eca49c70dc1f5140ee3603ab',1,'crow::response::end()'],['../structcrow_1_1response.html#a10da2e17421586b68f27ef1533ec677b',1,'crow::response::end(const std::string &body_part)']]], + ['estimate_5flength_368',['estimate_length',['../classcrow_1_1json_1_1wvalue.html#a5af23d208ed3d066a0fb5339350978c6',1,'crow::json::wvalue']]], + ['exception_5fhandler_369',['exception_handler',['../classcrow_1_1_crow.html#a872d39321015ac4f48ec8a6659dda99b',1,'crow::Crow']]] +]; diff --git a/1.2/reference/search/functions_5.html b/1.2/reference/search/functions_5.html new file mode 100644 index 000000000..9301d6b9c --- /dev/null +++ b/1.2/reference/search/functions_5.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_5.js b/1.2/reference/search/functions_5.js new file mode 100644 index 000000000..a9a7d1d17 --- /dev/null +++ b/1.2/reference/search/functions_5.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['feed_370',['feed',['../structcrow_1_1_h_t_t_p_parser.html#a9ca5bdc64f7ce0ffa836c6263da0da45',1,'crow::HTTPParser']]] +]; diff --git a/1.2/reference/search/functions_6.html b/1.2/reference/search/functions_6.html new file mode 100644 index 000000000..9c4f5fc65 --- /dev/null +++ b/1.2/reference/search/functions_6.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_6.js b/1.2/reference/search/functions_6.js new file mode 100644 index 000000000..ba550a16e --- /dev/null +++ b/1.2/reference/search/functions_6.js @@ -0,0 +1,13 @@ +var searchData= +[ + ['get_371',['get',['../classcrow_1_1query__string.html#a7db05380bed403b88cb2fe6a5fdd8d75',1,'crow::query_string']]], + ['get_5fbody_5fparams_372',['get_body_params',['../structcrow_1_1request.html#af2679155b496b7d8d80a82c0d9a175b5',1,'crow::request']]], + ['get_5fdefault_5ftimeout_373',['get_default_timeout',['../classcrow_1_1detail_1_1task__timer.html#ae11e1259251e562ea3be457457b3b287',1,'crow::detail::task_timer']]], + ['get_5fdict_374',['get_dict',['../classcrow_1_1query__string.html#af56add12ca6a7f0222956e353d1d40bb',1,'crow::query_string']]], + ['get_5ferror_375',['get_error',['../classcrow_1_1_router.html#a39beca1acc1997c68db0d34556b6cf87',1,'crow::Router']]], + ['get_5fheader_5fobject_376',['get_header_object',['../namespacecrow_1_1multipart.html#acecc1d3d17777095c4439ce5159f035d',1,'crow::multipart']]], + ['get_5fheader_5fvalue_377',['get_header_value',['../namespacecrow.html#ac0940ae1e094df6107d3a2604537279a',1,'crow']]], + ['get_5fheader_5fvalue_5fobject_378',['get_header_value_object',['../namespacecrow_1_1multipart.html#adb2a619f5ebb5d00a19d3e96dc3b0433',1,'crow::multipart']]], + ['get_5flist_379',['get_list',['../classcrow_1_1query__string.html#a657e5fe435375cd31229944ed2ad5608',1,'crow::query_string']]], + ['global_380',['global',['../structcrow_1_1_c_o_r_s_rules.html#a1684428b8d96050e7dbb852b526ec5a2',1,'crow::CORSRules::global()'],['../structcrow_1_1_c_o_r_s_handler.html#a969edd2b3d6768d067147839a430a976',1,'crow::CORSHandler::global()']]] +]; diff --git a/1.2/reference/search/functions_7.html b/1.2/reference/search/functions_7.html new file mode 100644 index 000000000..46b5c0f61 --- /dev/null +++ b/1.2/reference/search/functions_7.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_7.js b/1.2/reference/search/functions_7.js new file mode 100644 index 000000000..8611414a4 --- /dev/null +++ b/1.2/reference/search/functions_7.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['handle_381',['handle',['../classcrow_1_1_crow.html#a866cb219bb77c19326f39f431424e1c7',1,'crow::Crow']]], + ['handle_5ffragment_382',['handle_fragment',['../classcrow_1_1websocket_1_1_connection.html#a292002f44552e5eabd8dd65f476a4c28',1,'crow::websocket::Connection']]], + ['handle_5ffull_383',['handle_full',['../classcrow_1_1_crow.html#accf00be55c273297b758fa243f107018',1,'crow::Crow']]], + ['handle_5finitial_384',['handle_initial',['../classcrow_1_1_crow.html#a761ebd8c33ae35a3c61c7a160ad40789',1,'crow::Crow']]], + ['handle_5fupgrade_385',['handle_upgrade',['../classcrow_1_1_crow.html#a6e435bf5275735effd32647772bdbd04',1,'crow::Crow']]], + ['has_386',['has',['../classcrow_1_1json_1_1rvalue.html#a48ac4fff801f365fb2b82f1ed7ebe983',1,'crow::json::rvalue']]], + ['headers_387',['headers',['../structcrow_1_1_c_o_r_s_rules.html#aef945727e83b664728033243b2dd4977',1,'crow::CORSRules::headers(const std::string &header)'],['../structcrow_1_1_c_o_r_s_rules.html#acd966b06be1d0a8077cb4ead3defa2dd',1,'crow::CORSRules::headers(const std::string &header, Headers... header_list)']]] +]; diff --git a/1.2/reference/search/functions_8.html b/1.2/reference/search/functions_8.html new file mode 100644 index 000000000..31a1d9503 --- /dev/null +++ b/1.2/reference/search/functions_8.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_8.js b/1.2/reference/search/functions_8.js new file mode 100644 index 000000000..8a3c97784 --- /dev/null +++ b/1.2/reference/search/functions_8.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['i_388',['i',['../classcrow_1_1json_1_1rvalue.html#a1a9a1a3616d6484bf3dcdb941cf8e6da',1,'crow::json::rvalue']]], + ['ignore_389',['ignore',['../structcrow_1_1_c_o_r_s_rules.html#af7c411616ad51fb531a6ef0e0de4efe2',1,'crow::CORSRules']]], + ['is_5falive_390',['is_alive',['../structcrow_1_1response.html#ac29da52ee1e0b55086cd8eedd6c22da1',1,'crow::response']]], + ['is_5fcompleted_391',['is_completed',['../structcrow_1_1response.html#a9fb82c40e0c0844db70b7b86b4a23e9f',1,'crow::response']]], + ['is_5fempty_392',['is_empty',['../classcrow_1_1_trie.html#af2cada415bae6140779323f453a5a146',1,'crow::Trie']]], + ['is_5ffin_393',['is_FIN',['../classcrow_1_1websocket_1_1_connection.html#a98f4af4eac4b807f970667b0147869a4',1,'crow::websocket::Connection']]], + ['is_5fstatic_5ftype_394',['is_static_type',['../structcrow_1_1response.html#aff527a091cf5054e933a244b078648c1',1,'crow::response']]] +]; diff --git a/1.2/reference/search/functions_9.html b/1.2/reference/search/functions_9.html new file mode 100644 index 000000000..9a8e4290c --- /dev/null +++ b/1.2/reference/search/functions_9.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_9.js b/1.2/reference/search/functions_9.js new file mode 100644 index 000000000..2eda1aa5f --- /dev/null +++ b/1.2/reference/search/functions_9.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['lo_395',['lo',['../classcrow_1_1json_1_1rvalue.html#a2b938dacf1809bb38add4ac8bbeb46ed',1,'crow::json::rvalue']]], + ['loglevel_396',['loglevel',['../classcrow_1_1_crow.html#a7b6c225d3bba772eeadad89ebde68d21',1,'crow::Crow']]] +]; diff --git a/1.2/reference/search/functions_a.html b/1.2/reference/search/functions_a.html new file mode 100644 index 000000000..5ecc152ca --- /dev/null +++ b/1.2/reference/search/functions_a.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_a.js b/1.2/reference/search/functions_a.js new file mode 100644 index 000000000..0344fc7e3 --- /dev/null +++ b/1.2/reference/search/functions_a.js @@ -0,0 +1,11 @@ +var searchData= +[ + ['max_5fage_397',['max_age',['../structcrow_1_1_c_o_r_s_rules.html#aa3721c183750d7317d165c1b89013717',1,'crow::CORSRules']]], + ['max_5fpayload_398',['max_payload',['../classcrow_1_1_web_socket_rule.html#ad4d8b25025e767fbe9af7f7c4263c2cb',1,'crow::WebSocketRule']]], + ['message_399',['message',['../structcrow_1_1multipart_1_1message.html#a0007fa0cadffae1a8d16fac169d1527b',1,'crow::multipart::message::message(const ci_map &headers, const std::string &boundary, const std::vector< part > &sections)'],['../structcrow_1_1multipart_1_1message.html#a32946a0f39a8d024aaf4643116a7561b',1,'crow::multipart::message::message(const request &req)']]], + ['methods_400',['methods',['../structcrow_1_1_c_o_r_s_rules.html#a345cef92c2f28444e505646d429717cb',1,'crow::CORSRules::methods(crow::HTTPMethod method)'],['../structcrow_1_1_c_o_r_s_rules.html#a7ffe0b716c19efe9f576091c92cf83b4',1,'crow::CORSRules::methods(crow::HTTPMethod method, Methods... method_list)']]], + ['middlewares_401',['middlewares',['../structcrow_1_1_rule_parameter_traits.html#a137eb67383f095ce7ae5ef4da19656ab',1,'crow::RuleParameterTraits']]], + ['moved_402',['moved',['../structcrow_1_1response.html#a760bca5f5fdee03518d59d9538ce5432',1,'crow::response']]], + ['moved_5fperm_403',['moved_perm',['../structcrow_1_1response.html#a9ee58f8b775b2566418b298fe33c0dcc',1,'crow::response']]], + ['multithreaded_404',['multithreaded',['../classcrow_1_1_crow.html#a0149b20b7f6c0123292286f54638d456',1,'crow::Crow']]] +]; diff --git a/1.2/reference/search/functions_b.html b/1.2/reference/search/functions_b.html new file mode 100644 index 000000000..e301fedd7 --- /dev/null +++ b/1.2/reference/search/functions_b.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_b.js b/1.2/reference/search/functions_b.js new file mode 100644 index 000000000..422028e35 --- /dev/null +++ b/1.2/reference/search/functions_b.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['nt_405',['nt',['../classcrow_1_1json_1_1rvalue.html#a9bf75ffd4603990be7d0eaa192ac54fb',1,'crow::json::rvalue']]] +]; diff --git a/1.2/reference/search/functions_c.html b/1.2/reference/search/functions_c.html new file mode 100644 index 000000000..c4f326877 --- /dev/null +++ b/1.2/reference/search/functions_c.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_c.js b/1.2/reference/search/functions_c.js new file mode 100644 index 000000000..70c0ae17a --- /dev/null +++ b/1.2/reference/search/functions_c.js @@ -0,0 +1,8 @@ +var searchData= +[ + ['opcode_406',['opcode',['../classcrow_1_1websocket_1_1_connection.html#a6d74305323202dc7ebd07cbd3ee19f98',1,'crow::websocket::Connection']]], + ['operator_20double_407',['operator double',['../structcrow_1_1multipart_1_1header.html#a0b87278e0ebe8d323f46c9ed64fc385a',1,'crow::multipart::header::operator double()'],['../structcrow_1_1multipart_1_1part.html#ac9c4ebeeabe158725bc67cf14c9f957e',1,'crow::multipart::part::operator double()']]], + ['operator_20int_408',['operator int',['../structcrow_1_1multipart_1_1header.html#adff380493f414108eb67420d06d426ee',1,'crow::multipart::header::operator int()'],['../structcrow_1_1multipart_1_1part.html#a06851f0fd2d36b71139e8488fb646b7e',1,'crow::multipart::part::operator int()']]], + ['origin_409',['origin',['../structcrow_1_1_c_o_r_s_rules.html#a1d7a6517c7c256046065b2a02a25f6fa',1,'crow::CORSRules']]], + ['string_410',['string',['../classcrow_1_1json_1_1rvalue.html#a2d5dd8607112a132fe070dee432987ae',1,'crow::json::rvalue']]] +]; diff --git a/1.2/reference/search/functions_d.html b/1.2/reference/search/functions_d.html new file mode 100644 index 000000000..7a1ed065d --- /dev/null +++ b/1.2/reference/search/functions_d.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_d.js b/1.2/reference/search/functions_d.js new file mode 100644 index 000000000..05b80ee9f --- /dev/null +++ b/1.2/reference/search/functions_d.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['peek_5ffirst_411',['peek_first',['../structcrow_1_1session_1_1_expiration_tracker.html#a3a41ed909b0162aaf0ba02725e468951',1,'crow::session::ExpirationTracker']]], + ['pop_412',['pop',['../classcrow_1_1query__string.html#ab0a81b08a5531b98c08b1a6a268ebea1',1,'crow::query_string']]], + ['pop_5fdict_413',['pop_dict',['../classcrow_1_1query__string.html#a0744b06ff0709ebbe7c2a1646564508b',1,'crow::query_string']]], + ['pop_5flist_414',['pop_list',['../classcrow_1_1query__string.html#a8ef1a91122dc53e1235919e107fd1a9c',1,'crow::query_string']]], + ['port_415',['port',['../classcrow_1_1_crow.html#a365f9c95fc2bd8bb583967f499c1f4a1',1,'crow::Crow::port(std::uint16_t port)'],['../classcrow_1_1_crow.html#a87d0e10ed791c6847d8b7dfff2369aae',1,'crow::Crow::port()']]], + ['post_416',['post',['../structcrow_1_1request.html#a33aa146a3914864ce82ef22136451601',1,'crow::request::post()'],['../classcrow_1_1websocket_1_1_connection.html#ae55db4104d46350f5a9e040d32600984',1,'crow::websocket::Connection::post()']]], + ['prefix_417',['prefix',['../structcrow_1_1_c_o_r_s_rules.html#a98b09d1b3ebcc8db99a845333dc1ffff',1,'crow::CORSRules::prefix()'],['../structcrow_1_1_c_o_r_s_handler.html#a2805b07fdc18c36a89d5ad3886c3a5f5',1,'crow::CORSHandler::prefix()']]] +]; diff --git a/1.2/reference/search/functions_e.html b/1.2/reference/search/functions_e.html new file mode 100644 index 000000000..22d2a6bf5 --- /dev/null +++ b/1.2/reference/search/functions_e.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_e.js b/1.2/reference/search/functions_e.js new file mode 100644 index 000000000..b24d316ef --- /dev/null +++ b/1.2/reference/search/functions_e.js @@ -0,0 +1,13 @@ +var searchData= +[ + ['raw_5fsocket_418',['raw_socket',['../structcrow_1_1_socket_adaptor.html#a6c1efabfc9bf922308027f3d35c1f2c7',1,'crow::SocketAdaptor']]], + ['redirect_419',['redirect',['../structcrow_1_1response.html#ac04bbe2d4f54fd717cdffdb26af3e46f',1,'crow::response']]], + ['redirect_5fperm_420',['redirect_perm',['../structcrow_1_1response.html#a9e87a17c3cf8b434fd2a64a9b3d4b675',1,'crow::response']]], + ['render_421',['render',['../classcrow_1_1mustache_1_1template__t.html#a67caf7e23349a829b913c897ab882a8e',1,'crow::mustache::template_t::render() const'],['../classcrow_1_1mustache_1_1template__t.html#a77c579b71240695bd9fb634f48facd03',1,'crow::mustache::template_t::render(const context &ctx) const'],['../classcrow_1_1mustache_1_1template__t.html#ae8f2561efe590c0b5704df76b0c82aa5',1,'crow::mustache::template_t::render(const context &&ctx) const']]], + ['render_5fstring_422',['render_string',['../classcrow_1_1mustache_1_1template__t.html#a21199e08a066d7c66b5728354c2c40fd',1,'crow::mustache::template_t::render_string() const'],['../classcrow_1_1mustache_1_1template__t.html#af2258136c497b02eadfacbf50704de08',1,'crow::mustache::template_t::render_string(const context &ctx) const']]], + ['request_423',['request',['../structcrow_1_1request.html#a838c9a8c9a5eb2283d57e66f3630b5a6',1,'crow::request::request()'],['../structcrow_1_1request.html#a111b70ddb2a100a79415b539e152e145',1,'crow::request::request(HTTPMethod method, std::string raw_url, std::string url, query_string url_params, ci_map headers, std::string body, unsigned char http_major, unsigned char http_minor, bool has_keep_alive, bool has_close_connection, bool is_upgrade)']]], + ['route_424',['route',['../classcrow_1_1_crow.html#a5e1e54d49ff3015fd08f545b574ab44f',1,'crow::Crow']]], + ['route_5fdynamic_425',['route_dynamic',['../classcrow_1_1_crow.html#a0822a573ed653c3218f06c819a773ec2',1,'crow::Crow']]], + ['run_426',['run',['../classcrow_1_1_crow.html#a193d8b03f717234a841cd92f72c6b4b5',1,'crow::Crow']]], + ['run_5fasync_427',['run_async',['../classcrow_1_1_crow.html#aac4f72d944fb35caaf2d82cd21287269',1,'crow::Crow']]] +]; diff --git a/1.2/reference/search/functions_f.html b/1.2/reference/search/functions_f.html new file mode 100644 index 000000000..54b7dee08 --- /dev/null +++ b/1.2/reference/search/functions_f.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/functions_f.js b/1.2/reference/search/functions_f.js new file mode 100644 index 000000000..3b15b7dde --- /dev/null +++ b/1.2/reference/search/functions_f.js @@ -0,0 +1,21 @@ +var searchData= +[ + ['s_428',['s',['../classcrow_1_1json_1_1rvalue.html#ad94f27a14e60af841219279f70290858',1,'crow::json::rvalue']]], + ['schedule_429',['schedule',['../classcrow_1_1detail_1_1task__timer.html#ac1a35eb9b85887368b65e01c07d3c91c',1,'crow::detail::task_timer::schedule(const task_type &task)'],['../classcrow_1_1detail_1_1task__timer.html#a777c073f4e895c638d2cbbf6a27ad1fa',1,'crow::detail::task_timer::schedule(const task_type &task, std::uint8_t timeout)']]], + ['send_5fbinary_430',['send_binary',['../classcrow_1_1websocket_1_1_connection.html#ac8ba4036c9777f0e3af3531791d8ca62',1,'crow::websocket::Connection']]], + ['send_5fping_431',['send_ping',['../classcrow_1_1websocket_1_1_connection.html#ab5c1387014e5fdc0e9ebbb8661be04da',1,'crow::websocket::Connection']]], + ['send_5fpong_432',['send_pong',['../classcrow_1_1websocket_1_1_connection.html#a22c353583685e0e878813ab67333342c',1,'crow::websocket::Connection']]], + ['send_5ftext_433',['send_text',['../classcrow_1_1websocket_1_1_connection.html#a595b84a3c7206d4923286ac863b45ffb',1,'crow::websocket::Connection']]], + ['server_5fname_434',['server_name',['../classcrow_1_1_crow.html#ae0e400a1757bd68f716b82753a5a1a73',1,'crow::Crow']]], + ['set_5fdefault_5ftimeout_435',['set_default_timeout',['../classcrow_1_1detail_1_1task__timer.html#aa67cab7afc1646a4127b0c6c97e5f5ea',1,'crow::detail::task_timer']]], + ['set_5fheader_436',['set_header',['../structcrow_1_1response.html#ab2b9a9b9795fa6330bd47b66a716cb0b',1,'crow::response']]], + ['set_5fstatic_5ffile_5finfo_437',['set_static_file_info',['../structcrow_1_1response.html#a8f5e5caa08c3e658bccd03996e1a778a',1,'crow::response']]], + ['set_5fstatic_5ffile_5finfo_5funsafe_438',['set_static_file_info_unsafe',['../structcrow_1_1response.html#adaaa1a62451d41e6f3831463296b4c08',1,'crow::response']]], + ['size_439',['size',['../classcrow_1_1json_1_1wvalue.html#a1ded929c63fcb6e3c53be38e9b54c672',1,'crow::json::wvalue']]], + ['socket_440',['socket',['../classcrow_1_1_connection.html#adb5878dd700c30dae10f3fa8d06ecbab',1,'crow::Connection::socket()'],['../structcrow_1_1_socket_adaptor.html#a70c413ce6d8f9e2fe1e4852fc07f0928',1,'crow::SocketAdaptor::socket()']]], + ['ssl_5fchainfile_441',['ssl_chainfile',['../classcrow_1_1_crow.html#ade6bf7e56805c1112532807581293448',1,'crow::Crow']]], + ['ssl_5ffile_442',['ssl_file',['../classcrow_1_1_crow.html#a987e909347f0563f7b3dd97bbe271cea',1,'crow::Crow::ssl_file(const std::string &crt_filename, const std::string &key_filename)'],['../classcrow_1_1_crow.html#a3e5aa337025914852fcbfd1aebbd3241',1,'crow::Crow::ssl_file(const std::string &pem_filename)']]], + ['start_443',['start',['../classcrow_1_1websocket_1_1_connection.html#a928134640aa98a86f56a71735a41147a',1,'crow::websocket::Connection']]], + ['stop_444',['stop',['../classcrow_1_1_crow.html#a0266672657128919ab9a067d93f3868f',1,'crow::Crow']]], + ['stream_5fthreshold_445',['stream_threshold',['../classcrow_1_1_crow.html#ae92390d22f6fc99987c41a617be71d64',1,'crow::Crow::stream_threshold(size_t threshold)'],['../classcrow_1_1_crow.html#a0a7b45c935e58d199eb1bcba86003232',1,'crow::Crow::stream_threshold()']]] +]; diff --git a/1.2/reference/search/mag_sel.svg b/1.2/reference/search/mag_sel.svg new file mode 100644 index 000000000..03626f64a --- /dev/null +++ b/1.2/reference/search/mag_sel.svg @@ -0,0 +1,74 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/1.2/reference/search/namespaces_0.html b/1.2/reference/search/namespaces_0.html new file mode 100644 index 000000000..21db2c3a5 --- /dev/null +++ b/1.2/reference/search/namespaces_0.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/namespaces_0.js b/1.2/reference/search/namespaces_0.js new file mode 100644 index 000000000..3e415b9b7 --- /dev/null +++ b/1.2/reference/search/namespaces_0.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['crow_337',['crow',['../namespacecrow.html',1,'']]], + ['multipart_338',['multipart',['../namespacecrow_1_1multipart.html',1,'crow']]], + ['websocket_339',['websocket',['../namespacecrow_1_1websocket.html',1,'crow']]] +]; diff --git a/1.2/reference/search/namespaces_1.html b/1.2/reference/search/namespaces_1.html new file mode 100644 index 000000000..a01efeb1e --- /dev/null +++ b/1.2/reference/search/namespaces_1.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/namespaces_1.js b/1.2/reference/search/namespaces_1.js new file mode 100644 index 000000000..7596a4071 --- /dev/null +++ b/1.2/reference/search/namespaces_1.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['sha1_340',['sha1',['../namespacesha1.html',1,'']]] +]; diff --git a/1.2/reference/search/nomatches.html b/1.2/reference/search/nomatches.html new file mode 100644 index 000000000..2b9360b6b --- /dev/null +++ b/1.2/reference/search/nomatches.html @@ -0,0 +1,13 @@ + + + + + + + + +
+
No Matches
+
+ + diff --git a/1.2/reference/search/search.css b/1.2/reference/search/search.css new file mode 100644 index 000000000..a0dba441c --- /dev/null +++ b/1.2/reference/search/search.css @@ -0,0 +1,273 @@ +/*---------------- Search Box */ + +#FSearchBox { + float: left; +} + +#MSearchBox { + white-space : nowrap; + float: none; + margin-top: 0px; + right: 0px; + width: 170px; + height: 24px; + z-index: 102; + display: inline; + position: absolute; +} + +#MSearchBox .left +{ + display:block; + position:absolute; + left:10px; + width:20px; + height:19px; + background:url('search_l.png') no-repeat; + background-position:right; +} + +#MSearchSelect { + display:block; + position:absolute; + width:20px; + height:19px; +} + +.left #MSearchSelect { + left:4px; +} + +.right #MSearchSelect { + right:5px; +} + +#MSearchField { + display:block; + position:absolute; + height:19px; + background:url('search_m.png') repeat-x; + border:none; + width:111px; + margin-left:20px; + padding-left:4px; + color: #909090; + outline: none; + font: 9pt Arial, Verdana, sans-serif; + -webkit-border-radius: 0px; +} + +#FSearchBox #MSearchField { + margin-left:15px; +} + +#MSearchBox .right { + display:block; + position:absolute; + right:10px; + top:0px; + width:20px; + height:19px; + background:url('search_r.png') no-repeat; + background-position:left; +} + +#MSearchClose { + display: none; + position: absolute; + top: 4px; + background : none; + border: none; + margin: 0px 4px 0px 0px; + padding: 0px 0px; + outline: none; +} + +.left #MSearchClose { + left: 6px; +} + +.right #MSearchClose { + right: 2px; +} + +.MSearchBoxActive #MSearchField { + color: #000000; +} + +/*---------------- Search filter selection */ + +#MSearchSelectWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid #90A5CE; + background-color: #F9FAFC; + z-index: 10001; + padding-top: 4px; + padding-bottom: 4px; + -moz-border-radius: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +.SelectItem { + font: 8pt Arial, Verdana, sans-serif; + padding-left: 2px; + padding-right: 12px; + border: 0px; +} + +span.SelectionMark { + margin-right: 4px; + font-family: monospace; + outline-style: none; + text-decoration: none; +} + +a.SelectItem { + display: block; + outline-style: none; + color: #000000; + text-decoration: none; + padding-left: 6px; + padding-right: 12px; +} + +a.SelectItem:focus, +a.SelectItem:active { + color: #000000; + outline-style: none; + text-decoration: none; +} + +a.SelectItem:hover { + color: #FFFFFF; + background-color: #3D578C; + outline-style: none; + text-decoration: none; + cursor: pointer; + display: block; +} + +/*---------------- Search results window */ + +iframe#MSearchResults { + width: 60ex; + height: 15em; +} + +#MSearchResultsWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid #000; + background-color: #EEF1F7; + z-index:10000; +} + +/* ----------------------------------- */ + + +#SRIndex { + clear:both; + padding-bottom: 15px; +} + +.SREntry { + font-size: 10pt; + padding-left: 1ex; +} + +.SRPage .SREntry { + font-size: 8pt; + padding: 1px 5px; +} + +body.SRPage { + margin: 5px 2px; +} + +.SRChildren { + padding-left: 3ex; padding-bottom: .5em +} + +.SRPage .SRChildren { + display: none; +} + +.SRSymbol { + font-weight: bold; + color: #425E97; + font-family: Arial, Verdana, sans-serif; + text-decoration: none; + outline: none; +} + +a.SRScope { + display: block; + color: #425E97; + font-family: Arial, Verdana, sans-serif; + text-decoration: none; + outline: none; +} + +a.SRSymbol:focus, a.SRSymbol:active, +a.SRScope:focus, a.SRScope:active { + text-decoration: underline; +} + +span.SRScope { + padding-left: 4px; +} + +.SRPage .SRStatus { + padding: 2px 5px; + font-size: 8pt; + font-style: italic; +} + +.SRResult { + display: none; +} + +DIV.searchresults { + margin-left: 10px; + margin-right: 10px; +} + +/*---------------- External search page results */ + +.searchresult { + background-color: #F0F3F8; +} + +.pages b { + color: white; + padding: 5px 5px 3px 5px; + background-image: url("../tab_a.png"); + background-repeat: repeat-x; + text-shadow: 0 1px 1px #000000; +} + +.pages { + line-height: 17px; + margin-left: 4px; + text-decoration: none; +} + +.hl { + font-weight: bold; +} + +#searchresults { + margin-bottom: 20px; +} + +.searchpages { + margin-top: 10px; +} + diff --git a/1.2/reference/search/search.js b/1.2/reference/search/search.js new file mode 100644 index 000000000..fb226f734 --- /dev/null +++ b/1.2/reference/search/search.js @@ -0,0 +1,816 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ +function convertToId(search) +{ + var result = ''; + for (i=0;i do a search + { + this.Search(); + } + } + + this.OnSearchSelectKey = function(evt) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==40 && this.searchIndex0) // Up + { + this.searchIndex--; + this.OnSelectItem(this.searchIndex); + } + else if (e.keyCode==13 || e.keyCode==27) + { + this.OnSelectItem(this.searchIndex); + this.CloseSelectionWindow(); + this.DOMSearchField().focus(); + } + return false; + } + + // --------- Actions + + // Closes the results window. + this.CloseResultsWindow = function() + { + this.DOMPopupSearchResultsWindow().style.display = 'none'; + this.DOMSearchClose().style.display = 'none'; + this.Activate(false); + } + + this.CloseSelectionWindow = function() + { + this.DOMSearchSelectWindow().style.display = 'none'; + } + + // Performs a search. + this.Search = function() + { + this.keyTimeout = 0; + + // strip leading whitespace + var searchValue = this.DOMSearchField().value.replace(/^ +/, ""); + + var code = searchValue.toLowerCase().charCodeAt(0); + var idxChar = searchValue.substr(0, 1).toLowerCase(); + if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) // surrogate pair + { + idxChar = searchValue.substr(0, 2); + } + + var resultsPage; + var resultsPageWithSearch; + var hasResultsPage; + + var idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar); + if (idx!=-1) + { + var hexCode=idx.toString(16); + resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + this.extension; + resultsPageWithSearch = resultsPage+'?'+escape(searchValue); + hasResultsPage = true; + } + else // nothing available for this search term + { + resultsPage = this.resultsPath + '/nomatches' + this.extension; + resultsPageWithSearch = resultsPage; + hasResultsPage = false; + } + + window.frames.MSearchResults.location = resultsPageWithSearch; + var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); + + if (domPopupSearchResultsWindow.style.display!='block') + { + var domSearchBox = this.DOMSearchBox(); + this.DOMSearchClose().style.display = 'inline-block'; + if (this.insideFrame) + { + var domPopupSearchResults = this.DOMPopupSearchResults(); + domPopupSearchResultsWindow.style.position = 'relative'; + domPopupSearchResultsWindow.style.display = 'block'; + var width = document.body.clientWidth - 8; // the -8 is for IE :-( + domPopupSearchResultsWindow.style.width = width + 'px'; + domPopupSearchResults.style.width = width + 'px'; + } + else + { + var domPopupSearchResults = this.DOMPopupSearchResults(); + var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth; + var top = getYPos(domSearchBox) + 20; // domSearchBox.offsetHeight + 1; + domPopupSearchResultsWindow.style.display = 'block'; + left -= domPopupSearchResults.offsetWidth; + domPopupSearchResultsWindow.style.top = top + 'px'; + domPopupSearchResultsWindow.style.left = left + 'px'; + } + } + + this.lastSearchValue = searchValue; + this.lastResultsPage = resultsPage; + } + + // -------- Activation Functions + + // Activates or deactivates the search panel, resetting things to + // their default values if necessary. + this.Activate = function(isActive) + { + if (isActive || // open it + this.DOMPopupSearchResultsWindow().style.display == 'block' + ) + { + this.DOMSearchBox().className = 'MSearchBoxActive'; + + var searchField = this.DOMSearchField(); + + if (searchField.value == this.searchLabel) // clear "Search" term upon entry + { + searchField.value = ''; + this.searchActive = true; + } + } + else if (!isActive) // directly remove the panel + { + this.DOMSearchBox().className = 'MSearchBoxInactive'; + this.DOMSearchField().value = this.searchLabel; + this.searchActive = false; + this.lastSearchValue = '' + this.lastResultsPage = ''; + } + } +} + +// ----------------------------------------------------------------------- + +// The class that handles everything on the search results page. +function SearchResults(name) +{ + // The number of matches from the last run of . + this.lastMatchCount = 0; + this.lastKey = 0; + this.repeatOn = false; + + // Toggles the visibility of the passed element ID. + this.FindChildElement = function(id) + { + var parentElement = document.getElementById(id); + var element = parentElement.firstChild; + + while (element && element!=parentElement) + { + if (element.nodeName.toLowerCase() == 'div' && element.className == 'SRChildren') + { + return element; + } + + if (element.nodeName.toLowerCase() == 'div' && element.hasChildNodes()) + { + element = element.firstChild; + } + else if (element.nextSibling) + { + element = element.nextSibling; + } + else + { + do + { + element = element.parentNode; + } + while (element && element!=parentElement && !element.nextSibling); + + if (element && element!=parentElement) + { + element = element.nextSibling; + } + } + } + } + + this.Toggle = function(id) + { + var element = this.FindChildElement(id); + if (element) + { + if (element.style.display == 'block') + { + element.style.display = 'none'; + } + else + { + element.style.display = 'block'; + } + } + } + + // Searches for the passed string. If there is no parameter, + // it takes it from the URL query. + // + // Always returns true, since other documents may try to call it + // and that may or may not be possible. + this.Search = function(search) + { + if (!search) // get search word from URL + { + search = window.location.search; + search = search.substring(1); // Remove the leading '?' + search = unescape(search); + } + + search = search.replace(/^ +/, ""); // strip leading spaces + search = search.replace(/ +$/, ""); // strip trailing spaces + search = search.toLowerCase(); + search = convertToId(search); + + var resultRows = document.getElementsByTagName("div"); + var matches = 0; + + var i = 0; + while (i < resultRows.length) + { + var row = resultRows.item(i); + if (row.className == "SRResult") + { + var rowMatchName = row.id.toLowerCase(); + rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_' + + if (search.length<=rowMatchName.length && + rowMatchName.substr(0, search.length)==search) + { + row.style.display = 'block'; + matches++; + } + else + { + row.style.display = 'none'; + } + } + i++; + } + document.getElementById("Searching").style.display='none'; + if (matches == 0) // no results + { + document.getElementById("NoMatches").style.display='block'; + } + else // at least one result + { + document.getElementById("NoMatches").style.display='none'; + } + this.lastMatchCount = matches; + return true; + } + + // return the first item with index index or higher that is visible + this.NavNext = function(index) + { + var focusItem; + while (1) + { + var focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') + { + break; + } + else if (!focusItem) // last element + { + break; + } + focusItem=null; + index++; + } + return focusItem; + } + + this.NavPrev = function(index) + { + var focusItem; + while (1) + { + var focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') + { + break; + } + else if (!focusItem) // last element + { + break; + } + focusItem=null; + index--; + } + return focusItem; + } + + this.ProcessKeys = function(e) + { + if (e.type == "keydown") + { + this.repeatOn = false; + this.lastKey = e.keyCode; + } + else if (e.type == "keypress") + { + if (!this.repeatOn) + { + if (this.lastKey) this.repeatOn = true; + return false; // ignore first keypress after keydown + } + } + else if (e.type == "keyup") + { + this.lastKey = 0; + this.repeatOn = false; + } + return this.lastKey!=0; + } + + this.Nav = function(evt,itemIndex) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) // Up + { + var newIndex = itemIndex-1; + var focusItem = this.NavPrev(newIndex); + if (focusItem) + { + var child = this.FindChildElement(focusItem.parentNode.parentNode.id); + if (child && child.style.display == 'block') // children visible + { + var n=0; + var tmpElem; + while (1) // search for last child + { + tmpElem = document.getElementById('Item'+newIndex+'_c'+n); + if (tmpElem) + { + focusItem = tmpElem; + } + else // found it! + { + break; + } + n++; + } + } + } + if (focusItem) + { + focusItem.focus(); + } + else // return focus to search field + { + parent.document.getElementById("MSearchField").focus(); + } + } + else if (this.lastKey==40) // Down + { + var newIndex = itemIndex+1; + var focusItem; + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem && elem.style.display == 'block') // children visible + { + focusItem = document.getElementById('Item'+itemIndex+'_c0'); + } + if (!focusItem) focusItem = this.NavNext(newIndex); + if (focusItem) focusItem.focus(); + } + else if (this.lastKey==39) // Right + { + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'block'; + } + else if (this.lastKey==37) // Left + { + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'none'; + } + else if (this.lastKey==27) // Escape + { + parent.searchBox.CloseResultsWindow(); + parent.document.getElementById("MSearchField").focus(); + } + else if (this.lastKey==13) // Enter + { + return true; + } + return false; + } + + this.NavChild = function(evt,itemIndex,childIndex) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) // Up + { + if (childIndex>0) + { + var newIndex = childIndex-1; + document.getElementById('Item'+itemIndex+'_c'+newIndex).focus(); + } + else // already at first child, jump to parent + { + document.getElementById('Item'+itemIndex).focus(); + } + } + else if (this.lastKey==40) // Down + { + var newIndex = childIndex+1; + var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex); + if (!elem) // last child, jump to parent next parent + { + elem = this.NavNext(itemIndex+1); + } + if (elem) + { + elem.focus(); + } + } + else if (this.lastKey==27) // Escape + { + parent.searchBox.CloseResultsWindow(); + parent.document.getElementById("MSearchField").focus(); + } + else if (this.lastKey==13) // Enter + { + return true; + } + return false; + } +} + +function setKeyActions(elem,action) +{ + elem.setAttribute('onkeydown',action); + elem.setAttribute('onkeypress',action); + elem.setAttribute('onkeyup',action); +} + +function setClassAttr(elem,attr) +{ + elem.setAttribute('class',attr); + elem.setAttribute('className',attr); +} + +function createResults() +{ + var results = document.getElementById("SRResults"); + for (var e=0; e + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/typedefs_0.js b/1.2/reference/search/typedefs_0.js new file mode 100644 index 000000000..d430cad7b --- /dev/null +++ b/1.2/reference/search/typedefs_0.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['app_480',['App',['../namespacecrow.html#a153c1bf24903d1a8629ef6eaf045110b',1,'crow']]] +]; diff --git a/1.2/reference/search/typedefs_1.html b/1.2/reference/search/typedefs_1.html new file mode 100644 index 000000000..46cf01e62 --- /dev/null +++ b/1.2/reference/search/typedefs_1.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/typedefs_1.js b/1.2/reference/search/typedefs_1.js new file mode 100644 index 000000000..9e8610388 --- /dev/null +++ b/1.2/reference/search/typedefs_1.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['mp_5fmap_481',['mp_map',['../namespacecrow_1_1multipart.html#a071bb6d802c0edd823147fa6acaebb2b',1,'crow::multipart']]], + ['mph_5fmap_482',['mph_map',['../namespacecrow_1_1multipart.html#a6a2722b508669592976047a34d6eba0c',1,'crow::multipart']]] +]; diff --git a/1.2/reference/search/typedefs_2.html b/1.2/reference/search/typedefs_2.html new file mode 100644 index 000000000..6835ee65b --- /dev/null +++ b/1.2/reference/search/typedefs_2.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/typedefs_2.js b/1.2/reference/search/typedefs_2.js new file mode 100644 index 000000000..5bb518aeb --- /dev/null +++ b/1.2/reference/search/typedefs_2.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['self_5ft_483',['self_t',['../classcrow_1_1_crow.html#a5b0a203a6f9070ea8010227dcdbcec60',1,'crow::Crow']]], + ['server_5ft_484',['server_t',['../classcrow_1_1_crow.html#a5df810d2619e31c2f024cc4e45898997',1,'crow::Crow']]], + ['simpleapp_485',['SimpleApp',['../namespacecrow.html#a3603179c9794548cac2c9990685178b4',1,'crow']]], + ['ssl_5fserver_5ft_486',['ssl_server_t',['../classcrow_1_1_crow.html#aac04f81d0bc897267d092bb8af1513d4',1,'crow::Crow']]] +]; diff --git a/1.2/reference/search/variables_0.html b/1.2/reference/search/variables_0.html new file mode 100644 index 000000000..1e477c08c --- /dev/null +++ b/1.2/reference/search/variables_0.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_0.js b/1.2/reference/search/variables_0.js new file mode 100644 index 000000000..acf4f68dc --- /dev/null +++ b/1.2/reference/search/variables_0.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['body_456',['body',['../structcrow_1_1response.html#ae9f3cc153eac05954f1f4e599527892d',1,'crow::response::body()'],['../structcrow_1_1multipart_1_1part.html#acbfa0a181e86a89dccdf70d985365695',1,'crow::multipart::part::body()']]], + ['boundary_457',['boundary',['../structcrow_1_1multipart_1_1message.html#a56eb4bbf64d4930663ac4d5dd7b77d34',1,'crow::multipart::message']]] +]; diff --git a/1.2/reference/search/variables_1.html b/1.2/reference/search/variables_1.html new file mode 100644 index 000000000..ea73d9a49 --- /dev/null +++ b/1.2/reference/search/variables_1.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_1.js b/1.2/reference/search/variables_1.js new file mode 100644 index 000000000..a209e1c83 --- /dev/null +++ b/1.2/reference/search/variables_1.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['close_5fconnection_458',['close_connection',['../structcrow_1_1request.html#a4a3e4bcd0cd626ceaee38f4c17d28c8d',1,'crow::request']]], + ['code_459',['code',['../structcrow_1_1response.html#aabc1f9b3264b8c5a2d05dcb409e8ff3f',1,'crow::response']]], + ['compressed_460',['compressed',['../structcrow_1_1response.html#af87163fd1c7e18650c7691e07f58c7de',1,'crow::response']]] +]; diff --git a/1.2/reference/search/variables_2.html b/1.2/reference/search/variables_2.html new file mode 100644 index 000000000..0580462e9 --- /dev/null +++ b/1.2/reference/search/variables_2.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_2.js b/1.2/reference/search/variables_2.js new file mode 100644 index 000000000..81cd0c054 --- /dev/null +++ b/1.2/reference/search/variables_2.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['data_461',['data',['../structcrow_1_1http__parser.html#ac110503546750f343ad176dea0f48aa0',1,'crow::http_parser']]] +]; diff --git a/1.2/reference/search/variables_3.html b/1.2/reference/search/variables_3.html new file mode 100644 index 000000000..0d69e7619 --- /dev/null +++ b/1.2/reference/search/variables_3.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_3.js b/1.2/reference/search/variables_3.js new file mode 100644 index 000000000..3e4a60060 --- /dev/null +++ b/1.2/reference/search/variables_3.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['e_5f_462',['e_',['../structcrow_1_1json_1_1detail_1_1r__string.html#adeb368c4c0dfeb349bb32129e8dee23b',1,'crow::json::detail::r_string']]] +]; diff --git a/1.2/reference/search/variables_4.html b/1.2/reference/search/variables_4.html new file mode 100644 index 000000000..a4b6506bb --- /dev/null +++ b/1.2/reference/search/variables_4.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_4.js b/1.2/reference/search/variables_4.js new file mode 100644 index 000000000..85ab93d6d --- /dev/null +++ b/1.2/reference/search/variables_4.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['flags_463',['flags',['../structcrow_1_1http__parser.html#ab05c7677ce9af6c659e4401bb24484e7',1,'crow::http_parser']]] +]; diff --git a/1.2/reference/search/variables_5.html b/1.2/reference/search/variables_5.html new file mode 100644 index 000000000..7e345d16c --- /dev/null +++ b/1.2/reference/search/variables_5.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_5.js b/1.2/reference/search/variables_5.js new file mode 100644 index 000000000..e1b701294 --- /dev/null +++ b/1.2/reference/search/variables_5.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['headers_464',['headers',['../structcrow_1_1response.html#ae56cfc39f24a56748c11016842427fb3',1,'crow::response::headers()'],['../structcrow_1_1multipart_1_1part.html#a8ff7f3aac814d93500d475da150fcbc6',1,'crow::multipart::part::headers()'],['../structcrow_1_1multipart_1_1message.html#ae333adda5d66d21018a978e6a3c317dd',1,'crow::multipart::message::headers()']]], + ['http_5fmajor_465',['http_major',['../structcrow_1_1http__parser.html#a6f9afc90d7c8557570973524e41fc299',1,'crow::http_parser']]] +]; diff --git a/1.2/reference/search/variables_6.html b/1.2/reference/search/variables_6.html new file mode 100644 index 000000000..7d48e75e2 --- /dev/null +++ b/1.2/reference/search/variables_6.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_6.js b/1.2/reference/search/variables_6.js new file mode 100644 index 000000000..14e3c4528 --- /dev/null +++ b/1.2/reference/search/variables_6.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['keep_5falive_466',['keep_alive',['../structcrow_1_1request.html#a5148ce95969d261e50ee977c1dc7960c',1,'crow::request']]] +]; diff --git a/1.2/reference/search/variables_7.html b/1.2/reference/search/variables_7.html new file mode 100644 index 000000000..5c2634092 --- /dev/null +++ b/1.2/reference/search/variables_7.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_7.js b/1.2/reference/search/variables_7.js new file mode 100644 index 000000000..2b21eedf1 --- /dev/null +++ b/1.2/reference/search/variables_7.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['manual_5flength_5fheader_467',['manual_length_header',['../structcrow_1_1response.html#a95f300c05782e1934dad522b6d6588cf',1,'crow::response']]] +]; diff --git a/1.2/reference/search/variables_8.html b/1.2/reference/search/variables_8.html new file mode 100644 index 000000000..dc9ec54a5 --- /dev/null +++ b/1.2/reference/search/variables_8.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_8.js b/1.2/reference/search/variables_8.js new file mode 100644 index 000000000..9982de017 --- /dev/null +++ b/1.2/reference/search/variables_8.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['params_468',['params',['../structcrow_1_1multipart_1_1header.html#a18422d09aac9c5d5751799862d41a73c',1,'crow::multipart::header']]], + ['part_5fmap_469',['part_map',['../structcrow_1_1multipart_1_1message.html#a76d89e2bff4c90307053bcb895d334ec',1,'crow::multipart::message']]], + ['parts_470',['parts',['../structcrow_1_1multipart_1_1message.html#a05e9cf3feb60f4534af334b2dd5eadf2',1,'crow::multipart::message']]] +]; diff --git a/1.2/reference/search/variables_9.html b/1.2/reference/search/variables_9.html new file mode 100644 index 000000000..7b0147509 --- /dev/null +++ b/1.2/reference/search/variables_9.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_9.js b/1.2/reference/search/variables_9.js new file mode 100644 index 000000000..112883a76 --- /dev/null +++ b/1.2/reference/search/variables_9.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['raw_5furl_471',['raw_url',['../structcrow_1_1request.html#a72f5504a56f9ba70d7d33f86aaf9bc8a',1,'crow::request']]], + ['remote_5fip_5faddress_472',['remote_ip_address',['../structcrow_1_1request.html#aa8a04e30e2249f04614f233d25ffaad7',1,'crow::request']]], + ['req_473',['req',['../structcrow_1_1_h_t_t_p_parser.html#a56ce939040d6c582a62cea766e489d53',1,'crow::HTTPParser']]] +]; diff --git a/1.2/reference/search/variables_a.html b/1.2/reference/search/variables_a.html new file mode 100644 index 000000000..52a724d19 --- /dev/null +++ b/1.2/reference/search/variables_a.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_a.js b/1.2/reference/search/variables_a.js new file mode 100644 index 000000000..2cbb98a08 --- /dev/null +++ b/1.2/reference/search/variables_a.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['s_5f_474',['s_',['../structcrow_1_1json_1_1detail_1_1r__string.html#a9a0a048fb2cb904e8336926817947448',1,'crow::json::detail::r_string']]], + ['skip_5fbody_475',['skip_body',['../structcrow_1_1response.html#a548c4f5e059a7bb3b2560b7ac5800011',1,'crow::response']]] +]; diff --git a/1.2/reference/search/variables_b.html b/1.2/reference/search/variables_b.html new file mode 100644 index 000000000..f376b27af --- /dev/null +++ b/1.2/reference/search/variables_b.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_b.js b/1.2/reference/search/variables_b.js new file mode 100644 index 000000000..01352035f --- /dev/null +++ b/1.2/reference/search/variables_b.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['upgrade_476',['upgrade',['../structcrow_1_1request.html#ac4b5e2e32e2e0b633211925158b03559',1,'crow::request']]], + ['url_477',['url',['../structcrow_1_1request.html#aa3df34c56847d6d42887e73655276167',1,'crow::request']]], + ['url_5fparams_478',['url_params',['../structcrow_1_1request.html#a745d5a94e9e9ae1fed64674aae0194b0',1,'crow::request']]] +]; diff --git a/1.2/reference/search/variables_c.html b/1.2/reference/search/variables_c.html new file mode 100644 index 000000000..6019eba96 --- /dev/null +++ b/1.2/reference/search/variables_c.html @@ -0,0 +1,37 @@ + + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git a/1.2/reference/search/variables_c.js b/1.2/reference/search/variables_c.js new file mode 100644 index 000000000..c1e4a6142 --- /dev/null +++ b/1.2/reference/search/variables_c.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['value_479',['value',['../structcrow_1_1multipart_1_1header.html#aec60ea97914c4b9b102c3d5c1e89330a',1,'crow::multipart::header']]] +]; diff --git a/1.2/reference/session_8h_source.html b/1.2/reference/session_8h_source.html new file mode 100644 index 000000000..903690355 --- /dev/null +++ b/1.2/reference/session_8h_source.html @@ -0,0 +1,736 @@ + + + + + + + + Crow: include/crow/middlewares/session.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
session.h
+
+
+
1 #pragma once
+
2 
+
3 #include "crow/http_request.h"
+
4 #include "crow/http_response.h"
+
5 #include "crow/json.h"
+
6 #include "crow/utility.h"
+
7 #include "crow/middlewares/cookie_parser.h"
+
8 
+
9 #include <unordered_map>
+
10 #include <unordered_set>
+
11 #include <set>
+
12 #include <queue>
+
13 
+
14 #include <memory>
+
15 #include <string>
+
16 #include <cstdio>
+
17 #include <mutex>
+
18 
+
19 #include <fstream>
+
20 #include <sstream>
+
21 
+
22 #include <type_traits>
+
23 #include <functional>
+
24 #include <chrono>
+
25 
+
26 #ifdef CROW_CAN_USE_CPP17
+
27 #include <variant>
+
28 #endif
+
29 
+
30 namespace
+
31 {
+
32  // convert all integer values to int64_t
+
33  template<typename T>
+
34  using wrap_integral_t = typename std::conditional<
+
35  std::is_integral<T>::value && !std::is_same<bool, T>::value
+
36  // except for uint64_t because that could lead to overflow on conversion
+
37  && !std::is_same<uint64_t, T>::value,
+
38  int64_t, T>::type;
+
39 
+
40  // convert char[]/char* to std::string
+
41  template<typename T>
+
42  using wrap_char_t = typename std::conditional<
+
43  std::is_same<typename std::decay<T>::type, char*>::value,
+
44  std::string, T>::type;
+
45 
+
46  // Upgrade to correct type for multi_variant use
+
47  template<typename T>
+
48  using wrap_mv_t = wrap_char_t<wrap_integral_t<T>>;
+
49 } // namespace
+
50 
+
51 namespace crow
+
52 {
+
53  namespace session
+
54  {
+
55 
+
56 #ifdef CROW_CAN_USE_CPP17
+
57  using multi_value_types = black_magic::S<bool, int64_t, double, std::string>;
+
58 
+
59  /// A multi_value is a safe variant wrapper with json conversion support
+
60  struct multi_value
+
61  {
+
62  json::wvalue json() const
+
63  {
+
64  // clang-format off
+
65  return std::visit([](auto arg) {
+
66  return json::wvalue(arg);
+
67  }, v_);
+
68  // clang-format on
+
69  }
+
70 
+
71  static multi_value from_json(const json::rvalue&);
+
72 
+
73  std::string string() const
+
74  {
+
75  // clang-format off
+
76  return std::visit([](auto arg) {
+
77  if constexpr (std::is_same_v<decltype(arg), std::string>)
+
78  return arg;
+
79  else
+
80  return std::to_string(arg);
+
81  }, v_);
+
82  // clang-format on
+
83  }
+
84 
+
85  template<typename T, typename RT = wrap_mv_t<T>>
+
86  RT get(const T& fallback)
+
87  {
+
88  if (const RT* val = std::get_if<RT>(&v_)) return *val;
+
89  return fallback;
+
90  }
+
91 
+
92  template<typename T, typename RT = wrap_mv_t<T>>
+
93  void set(T val)
+
94  {
+
95  v_ = RT(std::move(val));
+
96  }
+
97 
+
98  typename multi_value_types::rebind<std::variant> v_;
+
99  };
+
100 
+
101  inline multi_value multi_value::from_json(const json::rvalue& rv)
+
102  {
+
103  using namespace json;
+
104  switch (rv.t())
+
105  {
+
106  case type::Number:
+
107  {
+
108  if (rv.nt() == num_type::Floating_point || rv.nt() == num_type::Double_precision_floating_point)
+
109  return multi_value{rv.d()};
+
110  else if (rv.nt() == num_type::Unsigned_integer)
+
111  return multi_value{int64_t(rv.u())};
+
112  else
+
113  return multi_value{rv.i()};
+
114  }
+
115  case type::False: return multi_value{false};
+
116  case type::True: return multi_value{true};
+
117  case type::String: return multi_value{std::string(rv)};
+
118  default: return multi_value{false};
+
119  }
+
120  }
+
121 #else
+
122  // Fallback for C++11/14 that uses a raw json::wvalue internally.
+
123  // This implementation consumes significantly more memory
+
124  // than the variant-based version
+
125  struct multi_value
+
126  {
+
127  json::wvalue json() const { return v_; }
+
128 
+
129  static multi_value from_json(const json::rvalue&);
+
130 
+
131  std::string string() const { return v_.dump(); }
+
132 
+
133  template<typename T, typename RT = wrap_mv_t<T>>
+
134  RT get(const T& fallback)
+
135  {
+
136  return json::wvalue_reader{v_}.get((const RT&)(fallback));
+
137  }
+
138 
+
139  template<typename T, typename RT = wrap_mv_t<T>>
+
140  void set(T val)
+
141  {
+
142  v_ = RT(std::move(val));
+
143  }
+
144 
+
145  json::wvalue v_;
+
146  };
+
147 
+
148  inline multi_value multi_value::from_json(const json::rvalue& rv)
+
149  {
+
150  return {rv};
+
151  }
+
152 #endif
+
153 
+
154  /// Expiration tracker keeps track of soonest-to-expire keys
+ +
156  {
+
157  using DataPair = std::pair<uint64_t /*time*/, std::string /*key*/>;
+
158 
+
159  /// Add key with time to tracker.
+
160  /// If the key is already present, it will be updated
+
161  void add(std::string key, uint64_t time)
+
162  {
+
163  auto it = times_.find(key);
+
164  if (it != times_.end()) remove(key);
+
165  times_[key] = time;
+
166  queue_.insert({time, std::move(key)});
+
167  }
+
168 
+
169  void remove(const std::string& key)
+
170  {
+
171  auto it = times_.find(key);
+
172  if (it != times_.end())
+
173  {
+
174  queue_.erase({it->second, key});
+
175  times_.erase(it);
+
176  }
+
177  }
+
178 
+
179  /// Get expiration time of soonest-to-expire entry
+
180  uint64_t peek_first() const
+
181  {
+
182  if (queue_.empty()) return std::numeric_limits<uint64_t>::max();
+
183  return queue_.begin()->first;
+
184  }
+
185 
+
186  std::string pop_first()
+
187  {
+
188  auto it = times_.find(queue_.begin()->second);
+
189  auto key = it->first;
+
190  times_.erase(it);
+
191  queue_.erase(queue_.begin());
+
192  return key;
+
193  }
+
194 
+
195  using iterator = typename std::set<DataPair>::const_iterator;
+
196 
+
197  iterator begin() const { return queue_.cbegin(); }
+
198 
+
199  iterator end() const { return queue_.cend(); }
+
200 
+
201  private:
+
202  std::set<DataPair> queue_;
+
203  std::unordered_map<std::string, uint64_t> times_;
+
204  };
+
205 
+
206  /// CachedSessions are shared across requests
+ +
208  {
+
209  std::string session_id;
+
210  std::string requested_session_id; // session hasn't been created yet, but a key was requested
+
211 
+
212  std::unordered_map<std::string, multi_value> entries;
+
213  std::unordered_set<std::string> dirty; // values that were changed after last load
+
214 
+
215  void* store_data;
+
216  bool requested_refresh;
+
217 
+
218  // number of references held - used for correctly destroying the cache.
+
219  // No need to be atomic, all SessionMiddleware accesses are synchronized
+
220  int referrers;
+
221  std::recursive_mutex mutex;
+
222  };
+
223  } // namespace session
+
224 
+
225  // SessionMiddleware allows storing securely and easily small snippets of user information
+
226  template<typename Store>
+ +
228  {
+
229 #ifdef CROW_CAN_USE_CPP17
+
230  using lock = std::scoped_lock<std::mutex>;
+
231  using rc_lock = std::scoped_lock<std::recursive_mutex>;
+
232 #else
+
233  using lock = std::lock_guard<std::mutex>;
+
234  using rc_lock = std::lock_guard<std::recursive_mutex>;
+
235 #endif
+
236 
+
237  struct context
+
238  {
+
239  // Get a mutex for locking this session
+
240  std::recursive_mutex& mutex()
+
241  {
+
242  check_node();
+
243  return node->mutex;
+
244  }
+
245 
+
246  // Check whether this session is already present
+
247  bool exists() { return bool(node); }
+
248 
+
249  // Get a value by key or fallback if it doesn't exist or is of another type
+
250  template<typename F>
+
251  auto get(const std::string& key, const F& fallback = F())
+
252  // This trick lets the multi_value deduce the return type from the fallback
+
253  // which allows both:
+
254  // context.get<std::string>("key")
+
255  // context.get("key", "") -> char[] is transformed into string by multivalue
+
256  // to return a string
+
257  -> decltype(std::declval<session::multi_value>().get<F>(std::declval<F>()))
+
258  {
+
259  if (!node) return fallback;
+
260  rc_lock l(node->mutex);
+
261 
+
262  auto it = node->entries.find(key);
+
263  if (it != node->entries.end()) return it->second.get<F>(fallback);
+
264  return fallback;
+
265  }
+
266 
+
267  // Set a value by key
+
268  template<typename T>
+
269  void set(const std::string& key, T value)
+
270  {
+
271  check_node();
+
272  rc_lock l(node->mutex);
+
273 
+
274  node->dirty.insert(key);
+
275  node->entries[key].set(std::move(value));
+
276  }
+
277 
+
278  bool contains(const std::string& key)
+
279  {
+
280  if (!node) return false;
+
281  return node->entries.find(key) != node->entries.end();
+
282  }
+
283 
+
284  // Atomically mutate a value with a function
+
285  template<typename Func>
+
286  void apply(const std::string& key, const Func& f)
+
287  {
+
288  using traits = utility::function_traits<Func>;
+
289  using arg = typename std::decay<typename traits::template arg<0>>::type;
+
290  using retv = typename std::decay<typename traits::result_type>::type;
+
291  check_node();
+
292  rc_lock l(node->mutex);
+
293  node->dirty.insert(key);
+
294  node->entries[key].set<retv>(f(node->entries[key].get(arg{})));
+
295  }
+
296 
+
297  // Remove a value from the session
+
298  void remove(const std::string& key)
+
299  {
+
300  if (!node) return;
+
301  rc_lock l(node->mutex);
+
302  node->dirty.insert(key);
+
303  node->entries.erase(key);
+
304  }
+
305 
+
306  // Format value by key as a string
+
307  std::string string(const std::string& key)
+
308  {
+
309  if (!node) return "";
+
310  rc_lock l(node->mutex);
+
311 
+
312  auto it = node->entries.find(key);
+
313  if (it != node->entries.end()) return it->second.string();
+
314  return "";
+
315  }
+
316 
+
317  // Get a list of keys present in session
+
318  std::vector<std::string> keys()
+
319  {
+
320  if (!node) return {};
+
321  rc_lock l(node->mutex);
+
322 
+
323  std::vector<std::string> out;
+
324  for (const auto& p : node->entries)
+
325  out.push_back(p.first);
+
326  return out;
+
327  }
+
328 
+
329  // Delay expiration by issuing another cookie with an updated expiration time
+
330  // and notifying the store
+
331  void refresh_expiration()
+
332  {
+
333  if (!node) return;
+
334  node->requested_refresh = true;
+
335  }
+
336 
+
337  private:
+
338  friend struct SessionMiddleware;
+
339 
+
340  void check_node()
+
341  {
+
342  if (!node) node = std::make_shared<session::CachedSession>();
+
343  }
+
344 
+
345  std::shared_ptr<session::CachedSession> node;
+
346  };
+
347 
+
348  template<typename... Ts>
+ +
350  CookieParser::Cookie cookie,
+
351  int id_length,
+
352  Ts... ts):
+
353  id_length_(id_length),
+
354  cookie_(cookie),
+
355  store_(std::forward<Ts>(ts)...), mutex_(new std::mutex{})
+
356  {}
+
357 
+
358  template<typename... Ts>
+
359  SessionMiddleware(Ts... ts):
+ +
361  CookieParser::Cookie("session").path("/").max_age(/*month*/ 30 * 24 * 60 * 60),
+
362  /*id_length */ 20, // around 10^34 possible combinations, but small enough to fit into SSO
+
363  std::forward<Ts>(ts)...)
+
364  {}
+
365 
+
366  template<typename AllContext>
+
367  void before_handle(request& /*req*/, response& /*res*/, context& ctx, AllContext& all_ctx)
+
368  {
+
369  lock l(*mutex_);
+
370 
+
371  auto& cookies = all_ctx.template get<CookieParser>();
+
372  auto session_id = load_id(cookies);
+
373  if (session_id == "") return;
+
374 
+
375  // search entry in cache
+
376  auto it = cache_.find(session_id);
+
377  if (it != cache_.end())
+
378  {
+
379  it->second->referrers++;
+
380  ctx.node = it->second;
+
381  return;
+
382  }
+
383 
+
384  // check this is a valid entry before loading
+
385  if (!store_.contains(session_id)) return;
+
386 
+
387  auto node = std::make_shared<session::CachedSession>();
+
388  node->session_id = session_id;
+
389  node->referrers = 1;
+
390 
+
391  try
+
392  {
+
393  store_.load(*node);
+
394  }
+
395  catch (...)
+
396  {
+
397  CROW_LOG_ERROR << "Exception occurred during session load";
+
398  return;
+
399  }
+
400 
+
401  ctx.node = node;
+
402  cache_[session_id] = node;
+
403  }
+
404 
+
405  template<typename AllContext>
+
406  void after_handle(request& /*req*/, response& /*res*/, context& ctx, AllContext& all_ctx)
+
407  {
+
408  lock l(*mutex_);
+
409  if (!ctx.node || --ctx.node->referrers > 0) return;
+
410  ctx.node->requested_refresh |= ctx.node->session_id == "";
+
411 
+
412  // generate new id
+
413  if (ctx.node->session_id == "")
+
414  {
+
415  // check for requested id
+
416  ctx.node->session_id = std::move(ctx.node->requested_session_id);
+
417  if (ctx.node->session_id == "")
+
418  {
+
419  ctx.node->session_id = utility::random_alphanum(id_length_);
+
420  }
+
421  }
+
422  else
+
423  {
+
424  cache_.erase(ctx.node->session_id);
+
425  }
+
426 
+
427  if (ctx.node->requested_refresh)
+
428  {
+
429  auto& cookies = all_ctx.template get<CookieParser>();
+
430  store_id(cookies, ctx.node->session_id);
+
431  }
+
432 
+
433  try
+
434  {
+
435  store_.save(*ctx.node);
+
436  }
+
437  catch (...)
+
438  {
+
439  CROW_LOG_ERROR << "Exception occurred during session save";
+
440  return;
+
441  }
+
442  }
+
443 
+
444  private:
+
445  std::string next_id()
+
446  {
+
447  std::string id;
+
448  do
+
449  {
+
450  id = utility::random_alphanum(id_length_);
+
451  } while (store_.contains(id));
+
452  return id;
+
453  }
+
454 
+
455  std::string load_id(const CookieParser::context& cookies)
+
456  {
+
457  return cookies.get_cookie(cookie_.name());
+
458  }
+
459 
+
460  void store_id(CookieParser::context& cookies, const std::string& session_id)
+
461  {
+
462  cookie_.value(session_id);
+
463  cookies.set_cookie(cookie_);
+
464  }
+
465 
+
466  private:
+
467  int id_length_;
+
468 
+
469  // prototype for cookie
+
470  CookieParser::Cookie cookie_;
+
471 
+
472  Store store_;
+
473 
+
474  // mutexes are immovable
+
475  std::unique_ptr<std::mutex> mutex_;
+
476  std::unordered_map<std::string, std::shared_ptr<session::CachedSession>> cache_;
+
477  };
+
478 
+
479  /// InMemoryStore stores all entries in memory
+ +
481  {
+
482  // Load a value into the session cache.
+
483  // A load is always followed by a save, no loads happen consecutively
+
484  void load(session::CachedSession& cn)
+
485  {
+
486  // load & stores happen sequentially, so moving is safe
+
487  cn.entries = std::move(entries[cn.session_id]);
+
488  }
+
489 
+
490  // Persist session data
+
491  void save(session::CachedSession& cn)
+
492  {
+
493  entries[cn.session_id] = std::move(cn.entries);
+
494  // cn.dirty is a list of changed keys since the last load
+
495  }
+
496 
+
497  bool contains(const std::string& key)
+
498  {
+
499  return entries.count(key) > 0;
+
500  }
+
501 
+
502  std::unordered_map<std::string, std::unordered_map<std::string, session::multi_value>> entries;
+
503  };
+
504 
+
505  // FileStore stores all data as json files in a folder.
+
506  // Files are deleted after expiration. Expiration refreshes are automatically picked up.
+
507  struct FileStore
+
508  {
+
509  FileStore(const std::string& folder, uint64_t expiration_seconds = /*month*/ 30 * 24 * 60 * 60):
+
510  path_(folder), expiration_seconds_(expiration_seconds)
+
511  {
+
512  std::ifstream ifs(get_filename(".expirations", false));
+
513 
+
514  auto current_ts = chrono_time();
+
515  std::string key;
+
516  uint64_t time;
+
517  while (ifs >> key >> time)
+
518  {
+
519  if (current_ts > time)
+
520  {
+
521  evict(key);
+
522  }
+
523  else if (contains(key))
+
524  {
+
525  expirations_.add(key, time);
+
526  }
+
527  }
+
528  }
+
529 
+
530  ~FileStore()
+
531  {
+
532  std::ofstream ofs(get_filename(".expirations", false), std::ios::trunc);
+
533  for (const auto& p : expirations_)
+
534  ofs << p.second << " " << p.first << "\n";
+
535  }
+
536 
+
537  // Delete expired entries
+
538  // At most 3 to prevent freezes
+
539  void handle_expired()
+
540  {
+
541  int deleted = 0;
+
542  auto current_ts = chrono_time();
+
543  while (current_ts > expirations_.peek_first() && deleted < 3)
+
544  {
+
545  evict(expirations_.pop_first());
+
546  deleted++;
+
547  }
+
548  }
+
549 
+
550  void load(session::CachedSession& cn)
+
551  {
+
552  handle_expired();
+
553 
+
554  std::ifstream file(get_filename(cn.session_id));
+
555 
+
556  std::stringstream buffer;
+
557  buffer << file.rdbuf() << std::endl;
+
558 
+
559  for (const auto& p : json::load(buffer.str()))
+
560  cn.entries[p.key()] = session::multi_value::from_json(p);
+
561  }
+
562 
+
563  void save(session::CachedSession& cn)
+
564  {
+
565  if (cn.requested_refresh)
+
566  expirations_.add(cn.session_id, chrono_time() + expiration_seconds_);
+
567  if (cn.dirty.empty()) return;
+
568 
+
569  std::ofstream file(get_filename(cn.session_id));
+
570  json::wvalue jw;
+
571  for (const auto& p : cn.entries)
+
572  jw[p.first] = p.second.json();
+
573  file << jw.dump() << std::flush;
+
574  }
+
575 
+
576  std::string get_filename(const std::string& key, bool suffix = true)
+
577  {
+
578  return utility::join_path(path_, key + (suffix ? ".json" : ""));
+
579  }
+
580 
+
581  bool contains(const std::string& key)
+
582  {
+
583  std::ifstream file(get_filename(key));
+
584  return file.good();
+
585  }
+
586 
+
587  void evict(const std::string& key)
+
588  {
+
589  std::remove(get_filename(key).c_str());
+
590  }
+
591 
+
592  uint64_t chrono_time() const
+
593  {
+
594  return std::chrono::duration_cast<std::chrono::seconds>(
+
595  std::chrono::system_clock::now().time_since_epoch())
+
596  .count();
+
597  }
+
598 
+
599  std::string path_;
+
600  uint64_t expiration_seconds_;
+
601  session::ExpirationTracker expirations_;
+
602  };
+
603 
+
604 } // namespace crow
+
JSON read value.
Definition: json.h:276
+
JSON write value.
Definition: json.h:1289
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+ + +
Definition: session.h:508
+
InMemoryStore stores all entries in memory.
Definition: session.h:481
+
Definition: session.h:238
+
Definition: session.h:228
+
Definition: json.h:2046
+
CachedSessions are shared across requests.
Definition: session.h:208
+
Expiration tracker keeps track of soonest-to-expire keys.
Definition: session.h:156
+
uint64_t peek_first() const
Get expiration time of soonest-to-expire entry.
Definition: session.h:180
+
void add(std::string key, uint64_t time)
Definition: session.h:161
+
Definition: session.h:126
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/settings_8h_source.html b/1.2/reference/settings_8h_source.html new file mode 100644 index 000000000..bd3ed59bf --- /dev/null +++ b/1.2/reference/settings_8h_source.html @@ -0,0 +1,184 @@ + + + + + + + + Crow: include/crow/settings.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
settings.h
+
+
+
1 #pragma once
+
2 // settings for crow
+
3 // TODO(ipkn) replace with runtime config. libucl?
+
4 
+
5 /* #ifdef - enables debug mode */
+
6 //#define CROW_ENABLE_DEBUG
+
7 
+
8 /* #ifdef - enables logging */
+
9 #define CROW_ENABLE_LOGGING
+
10 
+
11 /* #ifdef - enforces section 5.2 and 6.1 of RFC6455 (only accepting masked messages from clients) */
+
12 //#define CROW_ENFORCE_WS_SPEC
+
13 
+
14 /* #define - specifies log level */
+
15 /*
+
16  Debug = 0
+
17  Info = 1
+
18  Warning = 2
+
19  Error = 3
+
20  Critical = 4
+
21 
+
22  default to INFO
+
23 */
+
24 #ifndef CROW_LOG_LEVEL
+
25 #define CROW_LOG_LEVEL 1
+
26 #endif
+
27 
+
28 #ifndef CROW_STATIC_DIRECTORY
+
29 #define CROW_STATIC_DIRECTORY "static/"
+
30 #endif
+
31 #ifndef CROW_STATIC_ENDPOINT
+
32 #define CROW_STATIC_ENDPOINT "/static/<path>"
+
33 #endif
+
34 
+
35 // compiler flags
+
36 #if defined(_MSVC_LANG) && _MSVC_LANG >= 201402L
+
37 #define CROW_CAN_USE_CPP14
+
38 #endif
+
39 #if __cplusplus >= 201402L
+
40 #define CROW_CAN_USE_CPP14
+
41 #endif
+
42 
+
43 #if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
+
44 #define CROW_CAN_USE_CPP17
+
45 #endif
+
46 #if __cplusplus >= 201703L
+
47 #define CROW_CAN_USE_CPP17
+
48 #if defined(__GNUC__) && __GNUC__ < 8
+
49 #define CROW_FILESYSTEM_IS_EXPERIMENTAL
+
50 #endif
+
51 #endif
+
52 
+
53 #if defined(_MSC_VER)
+
54 #if _MSC_VER < 1900
+
55 #define CROW_MSVC_WORKAROUND
+
56 #define constexpr const
+
57 #define noexcept throw()
+
58 #endif
+
59 #endif
+
60 
+
61 #if defined(__GNUC__) && __GNUC__ == 8 && __GNUC_MINOR__ < 4
+
62 #if __cplusplus > 201103L
+
63 #define CROW_GCC83_WORKAROUND
+
64 #else
+
65 #error "GCC 8.1 - 8.3 has a bug that prevents Crow from compiling with C++11. Please update GCC to > 8.3 or use C++ > 11."
+
66 #endif
+
67 #endif
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/socket__adaptors_8h_source.html b/1.2/reference/socket__adaptors_8h_source.html new file mode 100644 index 000000000..f1f0d19d3 --- /dev/null +++ b/1.2/reference/socket__adaptors_8h_source.html @@ -0,0 +1,310 @@ + + + + + + + + Crow: include/crow/socket_adaptors.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
socket_adaptors.h
+
+
+
1 #pragma once
+
2 
+
3 #ifdef CROW_USE_BOOST
+
4 #include <boost/asio.hpp>
+
5 #include <boost/asio/version.hpp>
+
6 #ifdef CROW_ENABLE_SSL
+
7 #include <boost/asio/ssl.hpp>
+
8 #endif
+
9 #else
+
10 #ifndef ASIO_STANDALONE
+
11 #define ASIO_STANDALONE
+
12 #endif
+
13 #include <asio.hpp>
+
14 #include <asio/version.hpp>
+
15 #ifdef CROW_ENABLE_SSL
+
16 #include <asio/ssl.hpp>
+
17 #endif
+
18 #endif
+
19 #include "crow/settings.h"
+
20 
+
21 #if (CROW_USE_BOOST && BOOST_VERSION >= 107000) || (ASIO_VERSION >= 101300)
+
22 #define GET_IO_SERVICE(s) ((asio::io_context&)(s).get_executor().context())
+
23 #else
+
24 #define GET_IO_SERVICE(s) ((s).get_io_service())
+
25 #endif
+
26 
+
27 namespace crow
+
28 {
+
29 #ifdef CROW_USE_BOOST
+
30  namespace asio = boost::asio;
+
31  using error_code = boost::system::error_code;
+
32 #else
+
33  using error_code = asio::error_code;
+
34 #endif
+
35  using tcp = asio::ip::tcp;
+
36 
+
37  /// A wrapper for the asio::ip::tcp::socket and asio::ssl::stream
+ +
39  {
+
40  using context = void;
+
41  SocketAdaptor(asio::io_service& io_service, context*):
+
42  socket_(io_service)
+
43  {}
+
44 
+
45  asio::io_service& get_io_service()
+
46  {
+
47  return GET_IO_SERVICE(socket_);
+
48  }
+
49 
+
50  /// Get the TCP socket handling data trasfers, regardless of what layer is handling transfers on top of the socket.
+
51  tcp::socket& raw_socket()
+
52  {
+
53  return socket_;
+
54  }
+
55 
+
56  /// Get the object handling data transfers, this can be either a TCP socket or an SSL stream (if SSL is enabled).
+
57  tcp::socket& socket()
+
58  {
+
59  return socket_;
+
60  }
+
61 
+
62  tcp::endpoint remote_endpoint()
+
63  {
+
64  return socket_.remote_endpoint();
+
65  }
+
66 
+
67  bool is_open()
+
68  {
+
69  return socket_.is_open();
+
70  }
+
71 
+
72  void close()
+
73  {
+
74  error_code ec;
+
75  socket_.close(ec);
+
76  }
+
77 
+
78  void shutdown_readwrite()
+
79  {
+
80  error_code ec;
+
81  socket_.shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
+
82  }
+
83 
+
84  void shutdown_write()
+
85  {
+
86  error_code ec;
+
87  socket_.shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
+
88  }
+
89 
+
90  void shutdown_read()
+
91  {
+
92  error_code ec;
+
93  socket_.shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
+
94  }
+
95 
+
96  template<typename F>
+
97  void start(F f)
+
98  {
+
99  f(error_code());
+
100  }
+
101 
+
102  tcp::socket socket_;
+
103  };
+
104 
+
105 #ifdef CROW_ENABLE_SSL
+
106  struct SSLAdaptor
+
107  {
+
108  using context = asio::ssl::context;
+
109  using ssl_socket_t = asio::ssl::stream<tcp::socket>;
+
110  SSLAdaptor(asio::io_service& io_service, context* ctx):
+
111  ssl_socket_(new ssl_socket_t(io_service, *ctx))
+
112  {}
+
113 
+
114  asio::ssl::stream<tcp::socket>& socket()
+
115  {
+
116  return *ssl_socket_;
+
117  }
+
118 
+
119  tcp::socket::lowest_layer_type&
+
120  raw_socket()
+
121  {
+
122  return ssl_socket_->lowest_layer();
+
123  }
+
124 
+
125  tcp::endpoint remote_endpoint()
+
126  {
+
127  return raw_socket().remote_endpoint();
+
128  }
+
129 
+
130  bool is_open()
+
131  {
+
132  return ssl_socket_ ? raw_socket().is_open() : false;
+
133  }
+
134 
+
135  void close()
+
136  {
+
137  if (is_open())
+
138  {
+
139  error_code ec;
+
140  raw_socket().close(ec);
+
141  }
+
142  }
+
143 
+
144  void shutdown_readwrite()
+
145  {
+
146  if (is_open())
+
147  {
+
148  error_code ec;
+
149  raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_both, ec);
+
150  }
+
151  }
+
152 
+
153  void shutdown_write()
+
154  {
+
155  if (is_open())
+
156  {
+
157  error_code ec;
+
158  raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_send, ec);
+
159  }
+
160  }
+
161 
+
162  void shutdown_read()
+
163  {
+
164  if (is_open())
+
165  {
+
166  error_code ec;
+
167  raw_socket().shutdown(asio::socket_base::shutdown_type::shutdown_receive, ec);
+
168  }
+
169  }
+
170 
+
171  asio::io_service& get_io_service()
+
172  {
+
173  return GET_IO_SERVICE(raw_socket());
+
174  }
+
175 
+
176  template<typename F>
+
177  void start(F f)
+
178  {
+
179  ssl_socket_->async_handshake(asio::ssl::stream_base::server,
+
180  [f](const error_code& ec) {
+
181  f(ec);
+
182  });
+
183  }
+
184 
+
185  std::unique_ptr<asio::ssl::stream<tcp::socket>> ssl_socket_;
+
186  };
+
187 #endif
+
188 } // namespace crow
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
Definition: socket_adaptors.h:107
+
A wrapper for the asio::ip::tcp::socket and asio::ssl::stream.
Definition: socket_adaptors.h:39
+
tcp::socket & raw_socket()
Get the TCP socket handling data trasfers, regardless of what layer is handling transfers on top of t...
Definition: socket_adaptors.h:51
+
tcp::socket & socket()
Get the object handling data transfers, this can be either a TCP socket or an SSL stream (if SSL is e...
Definition: socket_adaptors.h:57
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/splitbar.png b/1.2/reference/splitbar.png new file mode 100644 index 000000000..fe895f2c5 Binary files /dev/null and b/1.2/reference/splitbar.png differ diff --git a/1.2/reference/structcrow_1_1_c_o_r_s_handler-members.html b/1.2/reference/structcrow_1_1_c_o_r_s_handler-members.html new file mode 100644 index 000000000..5314fbfbd --- /dev/null +++ b/1.2/reference/structcrow_1_1_c_o_r_s_handler-members.html @@ -0,0 +1,124 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::CORSHandler Member List
+
+
+ +

This is the complete list of members for crow::CORSHandler, including all inherited members.

+ + + + + + +
after_handle(crow::request &req, crow::response &res, context &) (defined in crow::CORSHandler)crow::CORSHandlerinline
before_handle(crow::request &, crow::response &, context &) (defined in crow::CORSHandler)crow::CORSHandlerinline
blueprint(const Blueprint &bp)crow::CORSHandlerinline
global()crow::CORSHandlerinline
prefix(const std::string &prefix)crow::CORSHandlerinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_c_o_r_s_handler.html b/1.2/reference/structcrow_1_1_c_o_r_s_handler.html new file mode 100644 index 000000000..baaaa8816 --- /dev/null +++ b/1.2/reference/structcrow_1_1_c_o_r_s_handler.html @@ -0,0 +1,159 @@ + + + + + + + + Crow: crow::CORSHandler Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::CORSHandler Struct Reference
+
+
+ +

CORSHandler is a global middleware for setting CORS headers. + More...

+ +

#include <cors.h>

+ + + + +

+Classes

struct  context
 
+ + + + + + + + + + + + + + +

+Public Member Functions

+void before_handle (crow::request &, crow::response &, context &)
 
+void after_handle (crow::request &req, crow::response &res, context &)
 
+CORSRulesprefix (const std::string &prefix)
 Handle CORS on a specific prefix path.
 
+CORSRulesblueprint (const Blueprint &bp)
 Handle CORS for a specific blueprint.
 
+CORSRulesglobal ()
 Get the global CORS policy.
 
+

Detailed Description

+

CORSHandler is a global middleware for setting CORS headers.

+

By default, it sets Access-Control-Allow-Origin/Methods/Headers to "*". The default behaviour can be changed with the global() cors rule. Additional rules for prexies can be added with prefix().

+

The documentation for this struct was generated from the following file:
    +
  • include/crow/middlewares/cors.h
  • +
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_c_o_r_s_handler.js b/1.2/reference/structcrow_1_1_c_o_r_s_handler.js new file mode 100644 index 000000000..56f0e5027 --- /dev/null +++ b/1.2/reference/structcrow_1_1_c_o_r_s_handler.js @@ -0,0 +1,9 @@ +var structcrow_1_1_c_o_r_s_handler = +[ + [ "context", "structcrow_1_1_c_o_r_s_handler_1_1context.html", null ], + [ "after_handle", "structcrow_1_1_c_o_r_s_handler.html#a7c0bc39a50cdf02f4203e63822e85105", null ], + [ "before_handle", "structcrow_1_1_c_o_r_s_handler.html#a3adb77a292af7924ec72d37604e8a367", null ], + [ "blueprint", "structcrow_1_1_c_o_r_s_handler.html#a218d078e061f8d2ad4c16e7db6022cad", null ], + [ "global", "structcrow_1_1_c_o_r_s_handler.html#a969edd2b3d6768d067147839a430a976", null ], + [ "prefix", "structcrow_1_1_c_o_r_s_handler.html#a2805b07fdc18c36a89d5ad3886c3a5f5", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_c_o_r_s_handler_1_1context.html b/1.2/reference/structcrow_1_1_c_o_r_s_handler_1_1context.html new file mode 100644 index 000000000..f3b89286a --- /dev/null +++ b/1.2/reference/structcrow_1_1_c_o_r_s_handler_1_1context.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: crow::CORSHandler::context Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::CORSHandler::context Struct Reference
+
+
+
The documentation for this struct was generated from the following file:
    +
  • include/crow/middlewares/cors.h
  • +
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_c_o_r_s_rules-members.html b/1.2/reference/structcrow_1_1_c_o_r_s_rules-members.html new file mode 100644 index 000000000..90a6a8580 --- /dev/null +++ b/1.2/reference/structcrow_1_1_c_o_r_s_rules-members.html @@ -0,0 +1,131 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::CORSRules Member List
+
+
+ +

This is the complete list of members for crow::CORSRules, including all inherited members.

+ + + + + + + + + + + + + +
allow_credentials()crow::CORSRulesinline
blueprint(const Blueprint &bp)crow::CORSRulesinline
crow::CORSHandler (defined in crow::CORSRules)crow::CORSRulesfriend
global()crow::CORSRulesinline
headers(const std::string &header)crow::CORSRulesinline
headers(const std::string &header, Headers... header_list)crow::CORSRulesinline
ignore()crow::CORSRulesinline
max_age(int max_age)crow::CORSRulesinline
methods(crow::HTTPMethod method)crow::CORSRulesinline
methods(crow::HTTPMethod method, Methods... method_list)crow::CORSRulesinline
origin(const std::string &origin)crow::CORSRulesinline
prefix(const std::string &prefix)crow::CORSRulesinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_c_o_r_s_rules.html b/1.2/reference/structcrow_1_1_c_o_r_s_rules.html new file mode 100644 index 000000000..8e54f77c2 --- /dev/null +++ b/1.2/reference/structcrow_1_1_c_o_r_s_rules.html @@ -0,0 +1,187 @@ + + + + + + + + Crow: crow::CORSRules Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::CORSRules Struct Reference
+
+
+ +

Used for tuning CORS policies. + More...

+ +

#include <cors.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

+CORSRulesorigin (const std::string &origin)
 Set Access-Control-Allow-Origin. Default is "*".
 
+CORSRulesmethods (crow::HTTPMethod method)
 Set Access-Control-Allow-Methods. Default is "*".
 
+template<typename... Methods>
CORSRulesmethods (crow::HTTPMethod method, Methods... method_list)
 Set Access-Control-Allow-Methods. Default is "*".
 
+CORSRulesheaders (const std::string &header)
 Set Access-Control-Allow-Headers. Default is "*".
 
+template<typename... Headers>
CORSRulesheaders (const std::string &header, Headers... header_list)
 Set Access-Control-Allow-Headers. Default is "*".
 
+CORSRulesmax_age (int max_age)
 Set Access-Control-Max-Age. Default is none.
 
+CORSRulesallow_credentials ()
 Enable Access-Control-Allow-Credentials.
 
+void ignore ()
 Ignore CORS and don't send any headers.
 
+CORSRulesprefix (const std::string &prefix)
 Handle CORS on specific prefix path.
 
+CORSRulesblueprint (const Blueprint &bp)
 Handle CORS for specific blueprint.
 
+CORSRulesglobal ()
 Global CORS policy.
 
+ + + +

+Friends

+struct crow::CORSHandler
 
+

Detailed Description

+

Used for tuning CORS policies.

+

The documentation for this struct was generated from the following file:
    +
  • include/crow/middlewares/cors.h
  • +
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_c_o_r_s_rules.js b/1.2/reference/structcrow_1_1_c_o_r_s_rules.js new file mode 100644 index 000000000..9fec5bbd1 --- /dev/null +++ b/1.2/reference/structcrow_1_1_c_o_r_s_rules.js @@ -0,0 +1,15 @@ +var structcrow_1_1_c_o_r_s_rules = +[ + [ "allow_credentials", "structcrow_1_1_c_o_r_s_rules.html#abca9739b2819cb386123997aab7b0dec", null ], + [ "blueprint", "structcrow_1_1_c_o_r_s_rules.html#ac26c50868a334cdd3601c7cd2f2a5248", null ], + [ "global", "structcrow_1_1_c_o_r_s_rules.html#a1684428b8d96050e7dbb852b526ec5a2", null ], + [ "headers", "structcrow_1_1_c_o_r_s_rules.html#aef945727e83b664728033243b2dd4977", null ], + [ "headers", "structcrow_1_1_c_o_r_s_rules.html#acd966b06be1d0a8077cb4ead3defa2dd", null ], + [ "ignore", "structcrow_1_1_c_o_r_s_rules.html#af7c411616ad51fb531a6ef0e0de4efe2", null ], + [ "max_age", "structcrow_1_1_c_o_r_s_rules.html#aa3721c183750d7317d165c1b89013717", null ], + [ "methods", "structcrow_1_1_c_o_r_s_rules.html#a345cef92c2f28444e505646d429717cb", null ], + [ "methods", "structcrow_1_1_c_o_r_s_rules.html#a7ffe0b716c19efe9f576091c92cf83b4", null ], + [ "origin", "structcrow_1_1_c_o_r_s_rules.html#a1d7a6517c7c256046065b2a02a25f6fa", null ], + [ "prefix", "structcrow_1_1_c_o_r_s_rules.html#a98b09d1b3ebcc8db99a845333dc1ffff", null ], + [ "crow::CORSHandler", "structcrow_1_1_c_o_r_s_rules.html#ab394f2c55f6b548c7a4b1c929cbe96a8", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_cookie_parser-members.html b/1.2/reference/structcrow_1_1_cookie_parser-members.html new file mode 100644 index 000000000..580ca395a --- /dev/null +++ b/1.2/reference/structcrow_1_1_cookie_parser-members.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::CookieParser Member List
+
+
+ +

This is the complete list of members for crow::CookieParser, including all inherited members.

+ + + +
after_handle(request &, response &res, context &ctx) (defined in crow::CookieParser)crow::CookieParserinline
before_handle(request &req, response &res, context &ctx) (defined in crow::CookieParser)crow::CookieParserinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_cookie_parser.html b/1.2/reference/structcrow_1_1_cookie_parser.html new file mode 100644 index 000000000..eb4d3f133 --- /dev/null +++ b/1.2/reference/structcrow_1_1_cookie_parser.html @@ -0,0 +1,141 @@ + + + + + + + + Crow: crow::CookieParser Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::CookieParser Struct Reference
+
+
+ + + + + + +

+Classes

struct  context
 
struct  Cookie
 
+ + + + + +

+Public Member Functions

+void before_handle (request &req, response &res, context &ctx)
 
+void after_handle (request &, response &res, context &ctx)
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_cookie_parser.js b/1.2/reference/structcrow_1_1_cookie_parser.js new file mode 100644 index 000000000..d47b8ec44 --- /dev/null +++ b/1.2/reference/structcrow_1_1_cookie_parser.js @@ -0,0 +1,7 @@ +var structcrow_1_1_cookie_parser = +[ + [ "context", "structcrow_1_1_cookie_parser_1_1context.html", "structcrow_1_1_cookie_parser_1_1context" ], + [ "Cookie", "structcrow_1_1_cookie_parser_1_1_cookie.html", "structcrow_1_1_cookie_parser_1_1_cookie" ], + [ "after_handle", "structcrow_1_1_cookie_parser.html#af9b029207147ece8c18a28dd4b1d8f2c", null ], + [ "before_handle", "structcrow_1_1_cookie_parser.html#a85053375273cc6a217136315cfe9d181", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_cookie_parser_1_1_cookie-members.html b/1.2/reference/structcrow_1_1_cookie_parser_1_1_cookie-members.html new file mode 100644 index 000000000..802f720c5 --- /dev/null +++ b/1.2/reference/structcrow_1_1_cookie_parser_1_1_cookie-members.html @@ -0,0 +1,133 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::CookieParser::Cookie Member List
+
+
+ +

This is the complete list of members for crow::CookieParser::Cookie, including all inherited members.

+ + + + + + + + + + + + + + + +
Cookie(const std::string &key, U &&value) (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
Cookie(const std::string &key) (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
Cookie(const Cookie &c) (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
domain(const std::string &name) (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
dump() const (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
expires(const std::tm &time) (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
httponly() (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
max_age(long long seconds) (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
name() (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
path(const std::string &path) (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
same_site(SameSitePolicy ssp) (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
SameSitePolicy enum name (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookie
secure() (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
value(U &&value) (defined in crow::CookieParser::Cookie)crow::CookieParser::Cookieinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_cookie_parser_1_1_cookie.html b/1.2/reference/structcrow_1_1_cookie_parser_1_1_cookie.html new file mode 100644 index 000000000..315aa8c20 --- /dev/null +++ b/1.2/reference/structcrow_1_1_cookie_parser_1_1_cookie.html @@ -0,0 +1,177 @@ + + + + + + + + Crow: crow::CookieParser::Cookie Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::CookieParser::Cookie Struct Reference
+
+
+ + + + +

+Public Types

enum class  SameSitePolicy { Strict +, Lax +, None + }
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

+template<typename U >
 Cookie (const std::string &key, U &&value)
 
Cookie (const std::string &key)
 
+std::string dump () const
 
+const std::string & name ()
 
+template<typename U >
Cookievalue (U &&value)
 
+Cookieexpires (const std::tm &time)
 
+Cookiemax_age (long long seconds)
 
+Cookiedomain (const std::string &name)
 
+Cookiepath (const std::string &path)
 
+Cookiesecure ()
 
+Cookiehttponly ()
 
+Cookiesame_site (SameSitePolicy ssp)
 
Cookie (const Cookie &c)
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_cookie_parser_1_1_cookie.js b/1.2/reference/structcrow_1_1_cookie_parser_1_1_cookie.js new file mode 100644 index 000000000..e901a6420 --- /dev/null +++ b/1.2/reference/structcrow_1_1_cookie_parser_1_1_cookie.js @@ -0,0 +1,21 @@ +var structcrow_1_1_cookie_parser_1_1_cookie = +[ + [ "SameSitePolicy", "structcrow_1_1_cookie_parser_1_1_cookie.html#a60148a93277a6c5219fcea36b1c30ea0", [ + [ "Strict", "structcrow_1_1_cookie_parser_1_1_cookie.html#a60148a93277a6c5219fcea36b1c30ea0a2e979835dd62324f5bfe217449ba4974", null ], + [ "Lax", "structcrow_1_1_cookie_parser_1_1_cookie.html#a60148a93277a6c5219fcea36b1c30ea0a6f0170fbfae85ec13f565665b8d74f3b", null ], + [ "None", "structcrow_1_1_cookie_parser_1_1_cookie.html#a60148a93277a6c5219fcea36b1c30ea0a6adf97f83acf6453d4a6a4b1070f3754", null ] + ] ], + [ "Cookie", "structcrow_1_1_cookie_parser_1_1_cookie.html#a7a7894fa9160191014647f558459e993", null ], + [ "Cookie", "structcrow_1_1_cookie_parser_1_1_cookie.html#afa9bbac95f1b04e72b8fcef65011d103", null ], + [ "Cookie", "structcrow_1_1_cookie_parser_1_1_cookie.html#a8dee0e3211bd6ec25a2aa3193ebe036f", null ], + [ "domain", "structcrow_1_1_cookie_parser_1_1_cookie.html#a2fd4f77628e86426f564eaab9aa212c4", null ], + [ "dump", "structcrow_1_1_cookie_parser_1_1_cookie.html#a2d291b28216f8f54e3274f359800ca59", null ], + [ "expires", "structcrow_1_1_cookie_parser_1_1_cookie.html#a7cb6e8c8724de976724591cbec48fae2", null ], + [ "httponly", "structcrow_1_1_cookie_parser_1_1_cookie.html#aabf1a5f643943fc7f4a78a634ddfb736", null ], + [ "max_age", "structcrow_1_1_cookie_parser_1_1_cookie.html#a0a1421a4513311c4548fdfe37d5b5b0e", null ], + [ "name", "structcrow_1_1_cookie_parser_1_1_cookie.html#af15e0a0fdfdc868424b7890e34fcaa63", null ], + [ "path", "structcrow_1_1_cookie_parser_1_1_cookie.html#a80bd431233cde1a2060e14c5e540f845", null ], + [ "same_site", "structcrow_1_1_cookie_parser_1_1_cookie.html#aed3a9f0fc3ca49e1d85bc6bdbd4fe93f", null ], + [ "secure", "structcrow_1_1_cookie_parser_1_1_cookie.html#a677824246762ee055c6aaf9801d65c39", null ], + [ "value", "structcrow_1_1_cookie_parser_1_1_cookie.html#ad55f9d8a8e1dd94c33c7ad0ff0684d32", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_cookie_parser_1_1context-members.html b/1.2/reference/structcrow_1_1_cookie_parser_1_1context-members.html new file mode 100644 index 000000000..7678ee40c --- /dev/null +++ b/1.2/reference/structcrow_1_1_cookie_parser_1_1context-members.html @@ -0,0 +1,124 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::CookieParser::context Member List
+
+
+ +

This is the complete list of members for crow::CookieParser::context, including all inherited members.

+ + + + + + +
CookieParser (defined in crow::CookieParser::context)crow::CookieParser::contextfriend
get_cookie(const std::string &key) const (defined in crow::CookieParser::context)crow::CookieParser::contextinline
jar (defined in crow::CookieParser::context)crow::CookieParser::context
set_cookie(const std::string &key, U &&value) (defined in crow::CookieParser::context)crow::CookieParser::contextinline
set_cookie(Cookie cookie) (defined in crow::CookieParser::context)crow::CookieParser::contextinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_cookie_parser_1_1context.html b/1.2/reference/structcrow_1_1_cookie_parser_1_1context.html new file mode 100644 index 000000000..31b299abc --- /dev/null +++ b/1.2/reference/structcrow_1_1_cookie_parser_1_1context.html @@ -0,0 +1,151 @@ + + + + + + + + Crow: crow::CookieParser::context Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::CookieParser::context Struct Reference
+
+
+ + + + + + + + + +

+Public Member Functions

+std::string get_cookie (const std::string &key) const
 
+template<typename U >
Cookieset_cookie (const std::string &key, U &&value)
 
+Cookieset_cookie (Cookie cookie)
 
+ + + +

+Public Attributes

+std::unordered_map< std::string, std::string > jar
 
+ + + +

+Friends

+struct CookieParser
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_cookie_parser_1_1context.js b/1.2/reference/structcrow_1_1_cookie_parser_1_1context.js new file mode 100644 index 000000000..b91de33f8 --- /dev/null +++ b/1.2/reference/structcrow_1_1_cookie_parser_1_1context.js @@ -0,0 +1,8 @@ +var structcrow_1_1_cookie_parser_1_1context = +[ + [ "get_cookie", "structcrow_1_1_cookie_parser_1_1context.html#adb47daa9a7ada1039e16f9f8e0d1a869", null ], + [ "set_cookie", "structcrow_1_1_cookie_parser_1_1context.html#a9cd0f07e304608e2f798d33ba222010d", null ], + [ "set_cookie", "structcrow_1_1_cookie_parser_1_1context.html#aeeaf1d983ddd027fc4bc66318be77d94", null ], + [ "CookieParser", "structcrow_1_1_cookie_parser_1_1context.html#aacecec6e195cca1f8139f2236c490e84", null ], + [ "jar", "structcrow_1_1_cookie_parser_1_1context.html#a65674550c5ee9ade652a4785c6b9b30c", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_file_store-members.html b/1.2/reference/structcrow_1_1_file_store-members.html new file mode 100644 index 000000000..e665e76a4 --- /dev/null +++ b/1.2/reference/structcrow_1_1_file_store-members.html @@ -0,0 +1,131 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::FileStore Member List
+
+
+ +

This is the complete list of members for crow::FileStore, including all inherited members.

+ + + + + + + + + + + + + +
chrono_time() const (defined in crow::FileStore)crow::FileStoreinline
contains(const std::string &key) (defined in crow::FileStore)crow::FileStoreinline
evict(const std::string &key) (defined in crow::FileStore)crow::FileStoreinline
expiration_seconds_ (defined in crow::FileStore)crow::FileStore
expirations_ (defined in crow::FileStore)crow::FileStore
FileStore(const std::string &folder, uint64_t expiration_seconds=30 *24 *60 *60) (defined in crow::FileStore)crow::FileStoreinline
get_filename(const std::string &key, bool suffix=true) (defined in crow::FileStore)crow::FileStoreinline
handle_expired() (defined in crow::FileStore)crow::FileStoreinline
load(session::CachedSession &cn) (defined in crow::FileStore)crow::FileStoreinline
path_ (defined in crow::FileStore)crow::FileStore
save(session::CachedSession &cn) (defined in crow::FileStore)crow::FileStoreinline
~FileStore() (defined in crow::FileStore)crow::FileStoreinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_file_store.html b/1.2/reference/structcrow_1_1_file_store.html new file mode 100644 index 000000000..a614ca594 --- /dev/null +++ b/1.2/reference/structcrow_1_1_file_store.html @@ -0,0 +1,164 @@ + + + + + + + + Crow: crow::FileStore Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::FileStore Struct Reference
+
+
+ + + + + + + + + + + + + + + + + + +

+Public Member Functions

FileStore (const std::string &folder, uint64_t expiration_seconds=30 *24 *60 *60)
 
+void handle_expired ()
 
+void load (session::CachedSession &cn)
 
+void save (session::CachedSession &cn)
 
+std::string get_filename (const std::string &key, bool suffix=true)
 
+bool contains (const std::string &key)
 
+void evict (const std::string &key)
 
+uint64_t chrono_time () const
 
+ + + + + + + +

+Public Attributes

+std::string path_
 
+uint64_t expiration_seconds_
 
+session::ExpirationTracker expirations_
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_file_store.js b/1.2/reference/structcrow_1_1_file_store.js new file mode 100644 index 000000000..463b7359a --- /dev/null +++ b/1.2/reference/structcrow_1_1_file_store.js @@ -0,0 +1,15 @@ +var structcrow_1_1_file_store = +[ + [ "FileStore", "structcrow_1_1_file_store.html#abb247faa5b37800faf1681c6135873cb", null ], + [ "~FileStore", "structcrow_1_1_file_store.html#a25d8848e78748954f0fc91f6a5b9b051", null ], + [ "chrono_time", "structcrow_1_1_file_store.html#ad2af99efb2b255865b3165e067ff62c2", null ], + [ "contains", "structcrow_1_1_file_store.html#a157b782b07d7cc33ca1df1a36dc7f123", null ], + [ "evict", "structcrow_1_1_file_store.html#aa4d0a57ad03688b86a9917b8dc85afc6", null ], + [ "get_filename", "structcrow_1_1_file_store.html#a12a26b21bf86b6004419255ea2a19356", null ], + [ "handle_expired", "structcrow_1_1_file_store.html#abd0f1c1384a68727e76fd2fc2b57f08e", null ], + [ "load", "structcrow_1_1_file_store.html#aeecb64930be79a90d445807c2985240f", null ], + [ "save", "structcrow_1_1_file_store.html#a88d9dae30b9a1c86440c7b783a1b1802", null ], + [ "expiration_seconds_", "structcrow_1_1_file_store.html#a78dabec9a902dbdb16ab320f91ee0d6f", null ], + [ "expirations_", "structcrow_1_1_file_store.html#a86339c643e5d6b1fb36b4973a7efc9bf", null ], + [ "path_", "structcrow_1_1_file_store.html#a6472dc22b56e7c677f6a63f1f44da64f", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_h_t_t_p_parser-members.html b/1.2/reference/structcrow_1_1_h_t_t_p_parser-members.html new file mode 100644 index 000000000..4907bfbf8 --- /dev/null +++ b/1.2/reference/structcrow_1_1_h_t_t_p_parser-members.html @@ -0,0 +1,152 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::HTTPParser< Handler > Member List
+
+
+ +

This is the complete list of members for crow::HTTPParser< Handler >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
allow_chunked_length (defined in crow::http_parser)crow::http_parser
clear() (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inline
content_length (defined in crow::http_parser)crow::http_parser
datacrow::http_parser
done() (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inline
feed(const char *buffer, int length)crow::HTTPParser< Handler >inline
flagscrow::http_parser
header_state (defined in crow::http_parser)crow::http_parser
http_errno (defined in crow::http_parser)crow::http_parser
http_majorcrow::http_parser
http_minor (defined in crow::http_parser)crow::http_parser
HTTPParser(Handler *handler) (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inline
index (defined in crow::http_parser)crow::http_parser
lenient_http_headers (defined in crow::http_parser)crow::http_parser
method (defined in crow::http_parser)crow::http_parser
nread (defined in crow::http_parser)crow::http_parser
on_body(http_parser *self_, const char *at, size_t length) (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inlinestatic
on_header_field(http_parser *self_, const char *at, size_t length) (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inlinestatic
on_header_value(http_parser *self_, const char *at, size_t length) (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inlinestatic
on_headers_complete(http_parser *self_) (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inlinestatic
on_message_begin(http_parser *) (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inlinestatic
on_message_complete(http_parser *self_) (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inlinestatic
on_method(http_parser *self_) (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inlinestatic
on_url(http_parser *self_, const char *at, size_t length) (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inlinestatic
process_header() (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inline
process_message() (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inline
process_url() (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inline
qs_point (defined in crow::http_parser)crow::http_parser
reqcrow::HTTPParser< Handler >
set_connection_parameters() (defined in crow::HTTPParser< Handler >)crow::HTTPParser< Handler >inline
state (defined in crow::http_parser)crow::http_parser
upgrade (defined in crow::http_parser)crow::http_parser
uses_transfer_encoding (defined in crow::http_parser)crow::http_parser
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_h_t_t_p_parser.html b/1.2/reference/structcrow_1_1_h_t_t_p_parser.html new file mode 100644 index 000000000..75b2079b0 --- /dev/null +++ b/1.2/reference/structcrow_1_1_h_t_t_p_parser.html @@ -0,0 +1,271 @@ + + + + + + + + Crow: crow::HTTPParser< Handler > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::HTTPParser< Handler > Struct Template Reference
+
+
+ +

A wrapper for nodejs/http-parser. + More...

+ +

#include <parser.h>

+
+Inheritance diagram for crow::HTTPParser< Handler >:
+
+
+ + +crow::http_parser + +
+ + + + + + + + + + + + + + + + + + + +

+Public Member Functions

HTTPParser (Handler *handler)
 
+bool feed (const char *buffer, int length)
 Parse a buffer into the different sections of an HTTP request.
 
+bool done ()
 
+void clear ()
 
+void process_url ()
 
+void process_header ()
 
+void process_message ()
 
+void set_connection_parameters ()
 
+ + + + + + + + + + + + + + + + + +

+Static Public Member Functions

+static int on_message_begin (http_parser *)
 
+static int on_method (http_parser *self_)
 
+static int on_url (http_parser *self_, const char *at, size_t length)
 
+static int on_header_field (http_parser *self_, const char *at, size_t length)
 
+static int on_header_value (http_parser *self_, const char *at, size_t length)
 
+static int on_headers_complete (http_parser *self_)
 
+static int on_body (http_parser *self_, const char *at, size_t length)
 
+static int on_message_complete (http_parser *self_)
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Attributes

request req
 
- Public Attributes inherited from crow::http_parser
unsigned int flags: 7
 
+unsigned int state: 8
 
+unsigned int header_state: 7
 
+unsigned int index: 5
 
+unsigned int uses_transfer_encoding: 1
 
+unsigned int allow_chunked_length: 1
 
+unsigned int lenient_http_headers: 1
 
+uint32_t nread
 
+uint64_t content_length
 
+unsigned long qs_point
 
unsigned char http_major
 
+unsigned char http_minor
 
+unsigned int method: 8
 
+unsigned int http_errno: 7
 
+unsigned int upgrade: 1
 
void * data
 
+

Detailed Description

+

template<typename Handler>
+struct crow::HTTPParser< Handler >

+ +

A wrapper for nodejs/http-parser.

+

Used to generate a crow::request from the TCP socket buffer.

+

Member Data Documentation

+ +

◆ req

+ +
+
+
+template<typename Handler >
+ + + + +
request crow::HTTPParser< Handler >::req
+
+

The final request that this parser outputs.

+

Data parsed is put directly into this object as soon as the related callback returns. (e.g. the request will have the cooorect method as soon as on_method() returns)

+ +
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_h_t_t_p_parser.js b/1.2/reference/structcrow_1_1_h_t_t_p_parser.js new file mode 100644 index 000000000..4a5b1d0d0 --- /dev/null +++ b/1.2/reference/structcrow_1_1_h_t_t_p_parser.js @@ -0,0 +1,12 @@ +var structcrow_1_1_h_t_t_p_parser = +[ + [ "HTTPParser", "structcrow_1_1_h_t_t_p_parser.html#a3659702ad1b853735ae6871f57bc2229", null ], + [ "clear", "structcrow_1_1_h_t_t_p_parser.html#abc4649eacc92efe28b8c41c1d434e749", null ], + [ "done", "structcrow_1_1_h_t_t_p_parser.html#af0421fefc211d39c6ee676c5ba0083a5", null ], + [ "feed", "structcrow_1_1_h_t_t_p_parser.html#a9ca5bdc64f7ce0ffa836c6263da0da45", null ], + [ "process_header", "structcrow_1_1_h_t_t_p_parser.html#ae074619da72a866f764821a981444404", null ], + [ "process_message", "structcrow_1_1_h_t_t_p_parser.html#a6aaafa15ad10e3165b547edecd66f174", null ], + [ "process_url", "structcrow_1_1_h_t_t_p_parser.html#a0c02c8afdc641b2b70d9d26772288370", null ], + [ "set_connection_parameters", "structcrow_1_1_h_t_t_p_parser.html#ac825fa6827ccc49ea6c6a1c3c203d919", null ], + [ "req", "structcrow_1_1_h_t_t_p_parser.html#a56ce939040d6c582a62cea766e489d53", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_h_t_t_p_parser.png b/1.2/reference/structcrow_1_1_h_t_t_p_parser.png new file mode 100644 index 000000000..2de83ada6 Binary files /dev/null and b/1.2/reference/structcrow_1_1_h_t_t_p_parser.png differ diff --git a/1.2/reference/structcrow_1_1_i_local_middleware-members.html b/1.2/reference/structcrow_1_1_i_local_middleware-members.html new file mode 100644 index 000000000..b6e725d66 --- /dev/null +++ b/1.2/reference/structcrow_1_1_i_local_middleware-members.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::ILocalMiddleware Member List
+
+
+ +

This is the complete list of members for crow::ILocalMiddleware, including all inherited members.

+ + +
call_global typedef (defined in crow::ILocalMiddleware)crow::ILocalMiddleware
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_i_local_middleware.html b/1.2/reference/structcrow_1_1_i_local_middleware.html new file mode 100644 index 000000000..ec1fb42ab --- /dev/null +++ b/1.2/reference/structcrow_1_1_i_local_middleware.html @@ -0,0 +1,137 @@ + + + + + + + + Crow: crow::ILocalMiddleware Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::ILocalMiddleware Struct Reference
+
+
+ +

Local middleware should extend ILocalMiddleware. + More...

+ +

#include <middleware.h>

+ + + + +

+Public Types

+using call_global = std::false_type
 
+

Detailed Description

+

Local middleware should extend ILocalMiddleware.

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_i_local_middleware.js b/1.2/reference/structcrow_1_1_i_local_middleware.js new file mode 100644 index 000000000..4f9ea81ce --- /dev/null +++ b/1.2/reference/structcrow_1_1_i_local_middleware.js @@ -0,0 +1,4 @@ +var structcrow_1_1_i_local_middleware = +[ + [ "call_global", "structcrow_1_1_i_local_middleware.html#a8497986d9589c15bad9f2241299b0213", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_in_memory_store-members.html b/1.2/reference/structcrow_1_1_in_memory_store-members.html new file mode 100644 index 000000000..ee01c60cd --- /dev/null +++ b/1.2/reference/structcrow_1_1_in_memory_store-members.html @@ -0,0 +1,123 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::InMemoryStore Member List
+
+
+ +

This is the complete list of members for crow::InMemoryStore, including all inherited members.

+ + + + + +
contains(const std::string &key) (defined in crow::InMemoryStore)crow::InMemoryStoreinline
entries (defined in crow::InMemoryStore)crow::InMemoryStore
load(session::CachedSession &cn) (defined in crow::InMemoryStore)crow::InMemoryStoreinline
save(session::CachedSession &cn) (defined in crow::InMemoryStore)crow::InMemoryStoreinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_in_memory_store.html b/1.2/reference/structcrow_1_1_in_memory_store.html new file mode 100644 index 000000000..50b843fec --- /dev/null +++ b/1.2/reference/structcrow_1_1_in_memory_store.html @@ -0,0 +1,150 @@ + + + + + + + + Crow: crow::InMemoryStore Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::InMemoryStore Struct Reference
+
+
+ +

InMemoryStore stores all entries in memory. + More...

+ +

#include <session.h>

+ + + + + + + + +

+Public Member Functions

+void load (session::CachedSession &cn)
 
+void save (session::CachedSession &cn)
 
+bool contains (const std::string &key)
 
+ + + +

+Public Attributes

+std::unordered_map< std::string, std::unordered_map< std::string, session::multi_value > > entries
 
+

Detailed Description

+

InMemoryStore stores all entries in memory.

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_in_memory_store.js b/1.2/reference/structcrow_1_1_in_memory_store.js new file mode 100644 index 000000000..fe24e0791 --- /dev/null +++ b/1.2/reference/structcrow_1_1_in_memory_store.js @@ -0,0 +1,7 @@ +var structcrow_1_1_in_memory_store = +[ + [ "contains", "structcrow_1_1_in_memory_store.html#a2d4c02f94bb38daf307f9cd771eae84b", null ], + [ "load", "structcrow_1_1_in_memory_store.html#af7f988e319fb83ccc6c5bab5e745bb2d", null ], + [ "save", "structcrow_1_1_in_memory_store.html#a4b55259e9a5fc9893a1bcc079e94a7d9", null ], + [ "entries", "structcrow_1_1_in_memory_store.html#a73591cb7887d570a35a9555fa378b205", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_rule_parameter_traits-members.html b/1.2/reference/structcrow_1_1_rule_parameter_traits-members.html new file mode 100644 index 000000000..a0e9c06e6 --- /dev/null +++ b/1.2/reference/structcrow_1_1_rule_parameter_traits-members.html @@ -0,0 +1,125 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::RuleParameterTraits< T > Member List
+
+
+ +

This is the complete list of members for crow::RuleParameterTraits< T >, including all inherited members.

+ + + + + + + +
methods(HTTPMethod method) (defined in crow::RuleParameterTraits< T >)crow::RuleParameterTraits< T >inline
methods(HTTPMethod method, MethodArgs... args_method) (defined in crow::RuleParameterTraits< T >)crow::RuleParameterTraits< T >inline
middlewares()crow::RuleParameterTraits< T >inline
name(std::string name) noexcept (defined in crow::RuleParameterTraits< T >)crow::RuleParameterTraits< T >inline
self_t typedef (defined in crow::RuleParameterTraits< T >)crow::RuleParameterTraits< T >
websocket(App *app) (defined in crow::RuleParameterTraits< T >)crow::RuleParameterTraits< T >inline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_rule_parameter_traits.html b/1.2/reference/structcrow_1_1_rule_parameter_traits.html new file mode 100644 index 000000000..8e574858d --- /dev/null +++ b/1.2/reference/structcrow_1_1_rule_parameter_traits.html @@ -0,0 +1,164 @@ + + + + + + + + Crow: crow::RuleParameterTraits< T > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::RuleParameterTraits< T > Struct Template Reference
+
+
+ +

Allows the user to assign parameters using functions. + More...

+ +

#include <routing.h>

+ + + + +

+Public Types

+using self_t = T
 
+ + + + + + + + + + + + + + + +

+Public Member Functions

+template<typename App >
WebSocketRule< App > & websocket (App *app)
 
+self_t & name (std::string name) noexcept
 
+self_t & methods (HTTPMethod method)
 
+template<typename... MethodArgs>
self_t & methods (HTTPMethod method, MethodArgs... args_method)
 
+template<typename App , typename... Middlewares>
self_t & middlewares ()
 Enable local middleware for this handler.
 
+

Detailed Description

+

template<typename T>
+struct crow::RuleParameterTraits< T >

+ +

Allows the user to assign parameters using functions.

+

rule.name("name").methods(HTTPMethod::POST)

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_rule_parameter_traits.js b/1.2/reference/structcrow_1_1_rule_parameter_traits.js new file mode 100644 index 000000000..f03572c37 --- /dev/null +++ b/1.2/reference/structcrow_1_1_rule_parameter_traits.js @@ -0,0 +1,9 @@ +var structcrow_1_1_rule_parameter_traits = +[ + [ "self_t", "structcrow_1_1_rule_parameter_traits.html#aa408e9880526bcb494f3600077a9cee2", null ], + [ "methods", "structcrow_1_1_rule_parameter_traits.html#a0c4d4d6919377ea393aa2f02b844f555", null ], + [ "methods", "structcrow_1_1_rule_parameter_traits.html#a3a302822f35e749cdefe4386e4a612c5", null ], + [ "middlewares", "structcrow_1_1_rule_parameter_traits.html#a137eb67383f095ce7ae5ef4da19656ab", null ], + [ "name", "structcrow_1_1_rule_parameter_traits.html#aa330efc6368bb7b66901122f1e8e4943", null ], + [ "websocket", "structcrow_1_1_rule_parameter_traits.html#a6cbe9a132da2321e2f1e1e30e82b2526", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_s_s_l_adaptor-members.html b/1.2/reference/structcrow_1_1_s_s_l_adaptor-members.html new file mode 100644 index 000000000..527d61b22 --- /dev/null +++ b/1.2/reference/structcrow_1_1_s_s_l_adaptor-members.html @@ -0,0 +1,133 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::SSLAdaptor Member List
+
+
+ +

This is the complete list of members for crow::SSLAdaptor, including all inherited members.

+ + + + + + + + + + + + + + + +
close() (defined in crow::SSLAdaptor)crow::SSLAdaptorinline
context typedef (defined in crow::SSLAdaptor)crow::SSLAdaptor
get_io_service() (defined in crow::SSLAdaptor)crow::SSLAdaptorinline
is_open() (defined in crow::SSLAdaptor)crow::SSLAdaptorinline
raw_socket() (defined in crow::SSLAdaptor)crow::SSLAdaptorinline
remote_endpoint() (defined in crow::SSLAdaptor)crow::SSLAdaptorinline
shutdown_read() (defined in crow::SSLAdaptor)crow::SSLAdaptorinline
shutdown_readwrite() (defined in crow::SSLAdaptor)crow::SSLAdaptorinline
shutdown_write() (defined in crow::SSLAdaptor)crow::SSLAdaptorinline
socket() (defined in crow::SSLAdaptor)crow::SSLAdaptorinline
ssl_socket_ (defined in crow::SSLAdaptor)crow::SSLAdaptor
ssl_socket_t typedef (defined in crow::SSLAdaptor)crow::SSLAdaptor
SSLAdaptor(asio::io_service &io_service, context *ctx) (defined in crow::SSLAdaptor)crow::SSLAdaptorinline
start(F f) (defined in crow::SSLAdaptor)crow::SSLAdaptorinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_s_s_l_adaptor.html b/1.2/reference/structcrow_1_1_s_s_l_adaptor.html new file mode 100644 index 000000000..740bdb379 --- /dev/null +++ b/1.2/reference/structcrow_1_1_s_s_l_adaptor.html @@ -0,0 +1,178 @@ + + + + + + + + Crow: crow::SSLAdaptor Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::SSLAdaptor Struct Reference
+
+
+ + + + + + +

+Public Types

+using context = asio::ssl::context
 
+using ssl_socket_t = asio::ssl::stream< tcp::socket >
 
+ + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

SSLAdaptor (asio::io_service &io_service, context *ctx)
 
+asio::ssl::stream< tcp::socket > & socket ()
 
+tcp::socket::lowest_layer_type & raw_socket ()
 
+tcp::endpoint remote_endpoint ()
 
+bool is_open ()
 
+void close ()
 
+void shutdown_readwrite ()
 
+void shutdown_write ()
 
+void shutdown_read ()
 
+asio::io_service & get_io_service ()
 
+template<typename F >
void start (F f)
 
+ + + +

+Public Attributes

+std::unique_ptr< asio::ssl::stream< tcp::socket > > ssl_socket_
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_s_s_l_adaptor.js b/1.2/reference/structcrow_1_1_s_s_l_adaptor.js new file mode 100644 index 000000000..e4318d703 --- /dev/null +++ b/1.2/reference/structcrow_1_1_s_s_l_adaptor.js @@ -0,0 +1,17 @@ +var structcrow_1_1_s_s_l_adaptor = +[ + [ "context", "structcrow_1_1_s_s_l_adaptor.html#a8b5be5dcdc6d7b28b93d3613040fc66b", null ], + [ "ssl_socket_t", "structcrow_1_1_s_s_l_adaptor.html#ace40044cb97fee064864ab375dfe2171", null ], + [ "SSLAdaptor", "structcrow_1_1_s_s_l_adaptor.html#a74f04032531498440cee8f2c6b57d628", null ], + [ "close", "structcrow_1_1_s_s_l_adaptor.html#aa6e8619be8b535936c014f79cb662fce", null ], + [ "get_io_service", "structcrow_1_1_s_s_l_adaptor.html#a05d255dff174c5b3dfe2a80133aad75e", null ], + [ "is_open", "structcrow_1_1_s_s_l_adaptor.html#ab8f3decb4671284242e55d8cc799a7e2", null ], + [ "raw_socket", "structcrow_1_1_s_s_l_adaptor.html#af9c3d9a72f56ea61359aaa506571a723", null ], + [ "remote_endpoint", "structcrow_1_1_s_s_l_adaptor.html#a495b69cfcb4a0c29daf81557d5c46cf7", null ], + [ "shutdown_read", "structcrow_1_1_s_s_l_adaptor.html#a91c648d2346541f53f359a218997bb20", null ], + [ "shutdown_readwrite", "structcrow_1_1_s_s_l_adaptor.html#aff3a31c4bc192cfd39918820af32ed56", null ], + [ "shutdown_write", "structcrow_1_1_s_s_l_adaptor.html#afab8ff8a2a83813f60382eb0227afce0", null ], + [ "socket", "structcrow_1_1_s_s_l_adaptor.html#a5a6a52d1b00fe0381907377564179f7e", null ], + [ "start", "structcrow_1_1_s_s_l_adaptor.html#a3baa6abe7b37a3fab1ff944dea72c648", null ], + [ "ssl_socket_", "structcrow_1_1_s_s_l_adaptor.html#afafda094b863619562062af01719ade2", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_session_middleware-members.html b/1.2/reference/structcrow_1_1_session_middleware-members.html new file mode 100644 index 000000000..3bb58e0e7 --- /dev/null +++ b/1.2/reference/structcrow_1_1_session_middleware-members.html @@ -0,0 +1,125 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::SessionMiddleware< Store > Member List
+
+
+ +

This is the complete list of members for crow::SessionMiddleware< Store >, including all inherited members.

+ + + + + + + +
after_handle(request &, response &, context &ctx, AllContext &all_ctx) (defined in crow::SessionMiddleware< Store >)crow::SessionMiddleware< Store >inline
before_handle(request &, response &, context &ctx, AllContext &all_ctx) (defined in crow::SessionMiddleware< Store >)crow::SessionMiddleware< Store >inline
lock typedef (defined in crow::SessionMiddleware< Store >)crow::SessionMiddleware< Store >
rc_lock typedef (defined in crow::SessionMiddleware< Store >)crow::SessionMiddleware< Store >
SessionMiddleware(CookieParser::Cookie cookie, int id_length, Ts... ts) (defined in crow::SessionMiddleware< Store >)crow::SessionMiddleware< Store >inline
SessionMiddleware(Ts... ts) (defined in crow::SessionMiddleware< Store >)crow::SessionMiddleware< Store >inline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_session_middleware.html b/1.2/reference/structcrow_1_1_session_middleware.html new file mode 100644 index 000000000..f313fbc08 --- /dev/null +++ b/1.2/reference/structcrow_1_1_session_middleware.html @@ -0,0 +1,159 @@ + + + + + + + + Crow: crow::SessionMiddleware< Store > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::SessionMiddleware< Store > Struct Template Reference
+
+
+ + + + +

+Classes

struct  context
 
+ + + + + +

+Public Types

+using lock = std::lock_guard< std::mutex >
 
+using rc_lock = std::lock_guard< std::recursive_mutex >
 
+ + + + + + + + + + + + + +

+Public Member Functions

+template<typename... Ts>
 SessionMiddleware (CookieParser::Cookie cookie, int id_length, Ts... ts)
 
+template<typename... Ts>
 SessionMiddleware (Ts... ts)
 
+template<typename AllContext >
void before_handle (request &, response &, context &ctx, AllContext &all_ctx)
 
+template<typename AllContext >
void after_handle (request &, response &, context &ctx, AllContext &all_ctx)
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_session_middleware.js b/1.2/reference/structcrow_1_1_session_middleware.js new file mode 100644 index 000000000..692c05a88 --- /dev/null +++ b/1.2/reference/structcrow_1_1_session_middleware.js @@ -0,0 +1,10 @@ +var structcrow_1_1_session_middleware = +[ + [ "context", "structcrow_1_1_session_middleware_1_1context.html", "structcrow_1_1_session_middleware_1_1context" ], + [ "lock", "structcrow_1_1_session_middleware.html#a65b80dd03c71fe58e56db2df3586725e", null ], + [ "rc_lock", "structcrow_1_1_session_middleware.html#a291d0e284dd9c9b0550a5ef4718336ff", null ], + [ "SessionMiddleware", "structcrow_1_1_session_middleware.html#a22ff1c31d382431eb42696b50b0cf64d", null ], + [ "SessionMiddleware", "structcrow_1_1_session_middleware.html#a16695b86bc55c4e28b850310f49e96c4", null ], + [ "after_handle", "structcrow_1_1_session_middleware.html#a650d4e9ec4c903b692f3543d8d9b83cd", null ], + [ "before_handle", "structcrow_1_1_session_middleware.html#a23dc5effe24c805defa4bce8b380b486", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_session_middleware_1_1context-members.html b/1.2/reference/structcrow_1_1_session_middleware_1_1context-members.html new file mode 100644 index 000000000..236b50f04 --- /dev/null +++ b/1.2/reference/structcrow_1_1_session_middleware_1_1context-members.html @@ -0,0 +1,130 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::SessionMiddleware< Store >::context Member List
+
+
+ +

This is the complete list of members for crow::SessionMiddleware< Store >::context, including all inherited members.

+ + + + + + + + + + + + +
apply(const std::string &key, const Func &f) (defined in crow::SessionMiddleware< Store >::context)crow::SessionMiddleware< Store >::contextinline
contains(const std::string &key) (defined in crow::SessionMiddleware< Store >::context)crow::SessionMiddleware< Store >::contextinline
exists() (defined in crow::SessionMiddleware< Store >::context)crow::SessionMiddleware< Store >::contextinline
get(const std::string &key, const F &fallback=F()) -> decltype(std::declval< session::multi_value >().get< F >(std::declval< F >())) (defined in crow::SessionMiddleware< Store >::context)crow::SessionMiddleware< Store >::contextinline
keys() (defined in crow::SessionMiddleware< Store >::context)crow::SessionMiddleware< Store >::contextinline
mutex() (defined in crow::SessionMiddleware< Store >::context)crow::SessionMiddleware< Store >::contextinline
refresh_expiration() (defined in crow::SessionMiddleware< Store >::context)crow::SessionMiddleware< Store >::contextinline
remove(const std::string &key) (defined in crow::SessionMiddleware< Store >::context)crow::SessionMiddleware< Store >::contextinline
SessionMiddleware (defined in crow::SessionMiddleware< Store >::context)crow::SessionMiddleware< Store >::contextfriend
set(const std::string &key, T value) (defined in crow::SessionMiddleware< Store >::context)crow::SessionMiddleware< Store >::contextinline
string(const std::string &key) (defined in crow::SessionMiddleware< Store >::context)crow::SessionMiddleware< Store >::contextinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_session_middleware_1_1context.html b/1.2/reference/structcrow_1_1_session_middleware_1_1context.html new file mode 100644 index 000000000..8cf26f188 --- /dev/null +++ b/1.2/reference/structcrow_1_1_session_middleware_1_1context.html @@ -0,0 +1,167 @@ + + + + + + + + Crow: crow::SessionMiddleware< Store >::context Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::SessionMiddleware< Store >::context Struct Reference
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

+std::recursive_mutex & mutex ()
 
+bool exists ()
 
+template<typename F >
auto get (const std::string &key, const F &fallback=F()) -> decltype(std::declval< session::multi_value >().get< F >(std::declval< F >()))
 
+template<typename T >
void set (const std::string &key, T value)
 
+bool contains (const std::string &key)
 
+template<typename Func >
void apply (const std::string &key, const Func &f)
 
+void remove (const std::string &key)
 
+std::string string (const std::string &key)
 
+std::vector< std::string > keys ()
 
+void refresh_expiration ()
 
+ + + +

+Friends

+struct SessionMiddleware
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_session_middleware_1_1context.js b/1.2/reference/structcrow_1_1_session_middleware_1_1context.js new file mode 100644 index 000000000..ef29033bb --- /dev/null +++ b/1.2/reference/structcrow_1_1_session_middleware_1_1context.js @@ -0,0 +1,14 @@ +var structcrow_1_1_session_middleware_1_1context = +[ + [ "apply", "structcrow_1_1_session_middleware_1_1context.html#ab33ab9f8d684255cf11633f02840c093", null ], + [ "contains", "structcrow_1_1_session_middleware_1_1context.html#aef298a499f4298cd3482e01aa4d8a189", null ], + [ "exists", "structcrow_1_1_session_middleware_1_1context.html#ab7e6f8147b14b7c707aa71c9f3355e9d", null ], + [ "get", "structcrow_1_1_session_middleware_1_1context.html#ab1079708972b627c72298e2628c8ee50", null ], + [ "keys", "structcrow_1_1_session_middleware_1_1context.html#ab80fefc0fd769758ee456a97ae94baa8", null ], + [ "mutex", "structcrow_1_1_session_middleware_1_1context.html#a84e055b418d92f4543513576fe285bfb", null ], + [ "refresh_expiration", "structcrow_1_1_session_middleware_1_1context.html#aeacc65b4d16d90223d24d4deb54ae693", null ], + [ "remove", "structcrow_1_1_session_middleware_1_1context.html#ae567ec6b3e255bd14ddb9795750d87b4", null ], + [ "set", "structcrow_1_1_session_middleware_1_1context.html#ac3ac42ff45eae328ca44b3c91eab48be", null ], + [ "string", "structcrow_1_1_session_middleware_1_1context.html#a88d30090b1b4af5a59499552aeffd868", null ], + [ "SessionMiddleware", "structcrow_1_1_session_middleware_1_1context.html#a93e20eae6e0fe6f6d0c85f772c928a95", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_socket_adaptor-members.html b/1.2/reference/structcrow_1_1_socket_adaptor-members.html new file mode 100644 index 000000000..a5b9be0e2 --- /dev/null +++ b/1.2/reference/structcrow_1_1_socket_adaptor-members.html @@ -0,0 +1,132 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::SocketAdaptor Member List
+
+
+ +

This is the complete list of members for crow::SocketAdaptor, including all inherited members.

+ + + + + + + + + + + + + + +
close() (defined in crow::SocketAdaptor)crow::SocketAdaptorinline
context typedef (defined in crow::SocketAdaptor)crow::SocketAdaptor
get_io_service() (defined in crow::SocketAdaptor)crow::SocketAdaptorinline
is_open() (defined in crow::SocketAdaptor)crow::SocketAdaptorinline
raw_socket()crow::SocketAdaptorinline
remote_endpoint() (defined in crow::SocketAdaptor)crow::SocketAdaptorinline
shutdown_read() (defined in crow::SocketAdaptor)crow::SocketAdaptorinline
shutdown_readwrite() (defined in crow::SocketAdaptor)crow::SocketAdaptorinline
shutdown_write() (defined in crow::SocketAdaptor)crow::SocketAdaptorinline
socket()crow::SocketAdaptorinline
socket_ (defined in crow::SocketAdaptor)crow::SocketAdaptor
SocketAdaptor(asio::io_service &io_service, context *) (defined in crow::SocketAdaptor)crow::SocketAdaptorinline
start(F f) (defined in crow::SocketAdaptor)crow::SocketAdaptorinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_socket_adaptor.html b/1.2/reference/structcrow_1_1_socket_adaptor.html new file mode 100644 index 000000000..1c87b3ab6 --- /dev/null +++ b/1.2/reference/structcrow_1_1_socket_adaptor.html @@ -0,0 +1,184 @@ + + + + + + + + Crow: crow::SocketAdaptor Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::SocketAdaptor Struct Reference
+
+
+ +

A wrapper for the asio::ip::tcp::socket and asio::ssl::stream. + More...

+ +

#include <socket_adaptors.h>

+ + + + +

+Public Types

+using context = void
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

SocketAdaptor (asio::io_service &io_service, context *)
 
+asio::io_service & get_io_service ()
 
+tcp::socket & raw_socket ()
 Get the TCP socket handling data trasfers, regardless of what layer is handling transfers on top of the socket.
 
+tcp::socket & socket ()
 Get the object handling data transfers, this can be either a TCP socket or an SSL stream (if SSL is enabled).
 
+tcp::endpoint remote_endpoint ()
 
+bool is_open ()
 
+void close ()
 
+void shutdown_readwrite ()
 
+void shutdown_write ()
 
+void shutdown_read ()
 
+template<typename F >
void start (F f)
 
+ + + +

+Public Attributes

+tcp::socket socket_
 
+

Detailed Description

+

A wrapper for the asio::ip::tcp::socket and asio::ssl::stream.

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_socket_adaptor.js b/1.2/reference/structcrow_1_1_socket_adaptor.js new file mode 100644 index 000000000..a66d70e6a --- /dev/null +++ b/1.2/reference/structcrow_1_1_socket_adaptor.js @@ -0,0 +1,16 @@ +var structcrow_1_1_socket_adaptor = +[ + [ "context", "structcrow_1_1_socket_adaptor.html#aca8c861d9a672785e17e127042d2f721", null ], + [ "SocketAdaptor", "structcrow_1_1_socket_adaptor.html#ad3a4be297a3871ae88d83ea34d8bb161", null ], + [ "close", "structcrow_1_1_socket_adaptor.html#af925b4f600663b2293741947297d730e", null ], + [ "get_io_service", "structcrow_1_1_socket_adaptor.html#afdb850058d441b7cb31a5aed7259dfa2", null ], + [ "is_open", "structcrow_1_1_socket_adaptor.html#a2630c4db0c3065e7c7b396515571941a", null ], + [ "raw_socket", "structcrow_1_1_socket_adaptor.html#a6c1efabfc9bf922308027f3d35c1f2c7", null ], + [ "remote_endpoint", "structcrow_1_1_socket_adaptor.html#a23fb23ae334da14488199fe04d5ea066", null ], + [ "shutdown_read", "structcrow_1_1_socket_adaptor.html#a4aee4293c6aefd1eb682f2673f7ce1b2", null ], + [ "shutdown_readwrite", "structcrow_1_1_socket_adaptor.html#a7f779ee234e09a19d1e3aa42734656a2", null ], + [ "shutdown_write", "structcrow_1_1_socket_adaptor.html#a6d533f036b670f67d98739f0b1a2e074", null ], + [ "socket", "structcrow_1_1_socket_adaptor.html#a70c413ce6d8f9e2fe1e4852fc07f0928", null ], + [ "start", "structcrow_1_1_socket_adaptor.html#a074e679e5abd86af6bcd3f505accfb4e", null ], + [ "socket_", "structcrow_1_1_socket_adaptor.html#adfae304955845303cee26c31910b1f2c", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_trie_1_1_node-members.html b/1.2/reference/structcrow_1_1_trie_1_1_node-members.html new file mode 100644 index 000000000..88e147b6b --- /dev/null +++ b/1.2/reference/structcrow_1_1_trie_1_1_node-members.html @@ -0,0 +1,126 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::Trie::Node Member List
+
+
+ +

This is the complete list of members for crow::Trie::Node, including all inherited members.

+ + + + + + + + +
add_child_node() (defined in crow::Trie::Node)crow::Trie::Nodeinline
blueprint_index (defined in crow::Trie::Node)crow::Trie::Node
children (defined in crow::Trie::Node)crow::Trie::Node
IsSimpleNode() const (defined in crow::Trie::Node)crow::Trie::Nodeinline
key (defined in crow::Trie::Node)crow::Trie::Node
param (defined in crow::Trie::Node)crow::Trie::Node
rule_index (defined in crow::Trie::Node)crow::Trie::Node
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_trie_1_1_node.html b/1.2/reference/structcrow_1_1_trie_1_1_node.html new file mode 100644 index 000000000..cc1a934f4 --- /dev/null +++ b/1.2/reference/structcrow_1_1_trie_1_1_node.html @@ -0,0 +1,152 @@ + + + + + + + + Crow: crow::Trie::Node Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::Trie::Node Struct Reference
+
+
+ + + + + + +

+Public Member Functions

+bool IsSimpleNode () const
 
+Nodeadd_child_node ()
 
+ + + + + + + + + + + +

+Public Attributes

+uint16_t rule_index {}
 
+uint16_t blueprint_index {INVALID_BP_ID}
 
+std::string key
 
+ParamType param = ParamType::MAX
 
+std::vector< Nodechildren
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_trie_1_1_node.js b/1.2/reference/structcrow_1_1_trie_1_1_node.js new file mode 100644 index 000000000..a71f660d3 --- /dev/null +++ b/1.2/reference/structcrow_1_1_trie_1_1_node.js @@ -0,0 +1,10 @@ +var structcrow_1_1_trie_1_1_node = +[ + [ "add_child_node", "structcrow_1_1_trie_1_1_node.html#a01a7a05b0314be97732edaba119184d8", null ], + [ "IsSimpleNode", "structcrow_1_1_trie_1_1_node.html#ae72aa7fc92fe39cd902dff0dcc9e69e8", null ], + [ "blueprint_index", "structcrow_1_1_trie_1_1_node.html#a960b2f4cf23c860f7b15ab3a9ba3c3f5", null ], + [ "children", "structcrow_1_1_trie_1_1_node.html#a35797ec0d9308ecec372d58fd1ed7296", null ], + [ "key", "structcrow_1_1_trie_1_1_node.html#a355b279db31bd1cead3f7de89a6f55f0", null ], + [ "param", "structcrow_1_1_trie_1_1_node.html#a7aac45bf193240463b5e74945edb74b1", null ], + [ "rule_index", "structcrow_1_1_trie_1_1_node.html#a8e1344b611cffe1000436ca2e527420c", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_u_t_f8-members.html b/1.2/reference/structcrow_1_1_u_t_f8-members.html new file mode 100644 index 000000000..e5ae54b11 --- /dev/null +++ b/1.2/reference/structcrow_1_1_u_t_f8-members.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::UTF8 Member List
+
+
+ +

This is the complete list of members for crow::UTF8, including all inherited members.

+ + + +
after_handle(request &, response &res, context &) (defined in crow::UTF8)crow::UTF8inline
before_handle(request &, response &, context &) (defined in crow::UTF8)crow::UTF8inline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_u_t_f8.html b/1.2/reference/structcrow_1_1_u_t_f8.html new file mode 100644 index 000000000..5ba0b5053 --- /dev/null +++ b/1.2/reference/structcrow_1_1_u_t_f8.html @@ -0,0 +1,139 @@ + + + + + + + + Crow: crow::UTF8 Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::UTF8 Struct Reference
+
+
+ + + + +

+Classes

struct  context
 
+ + + + + +

+Public Member Functions

+void before_handle (request &, response &, context &)
 
+void after_handle (request &, response &res, context &)
 
+
The documentation for this struct was generated from the following file:
    +
  • include/crow/middlewares/utf-8.h
  • +
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_u_t_f8.js b/1.2/reference/structcrow_1_1_u_t_f8.js new file mode 100644 index 000000000..70deb3d33 --- /dev/null +++ b/1.2/reference/structcrow_1_1_u_t_f8.js @@ -0,0 +1,6 @@ +var structcrow_1_1_u_t_f8 = +[ + [ "context", "structcrow_1_1_u_t_f8_1_1context.html", null ], + [ "after_handle", "structcrow_1_1_u_t_f8.html#afad343b6dec968fcb6ec9a8d86c951f7", null ], + [ "before_handle", "structcrow_1_1_u_t_f8.html#a92ca5420e9bce3a4c0fb07807bc94a2f", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1_u_t_f8_1_1context.html b/1.2/reference/structcrow_1_1_u_t_f8_1_1context.html new file mode 100644 index 000000000..f588670d1 --- /dev/null +++ b/1.2/reference/structcrow_1_1_u_t_f8_1_1context.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: crow::UTF8::context Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::UTF8::context Struct Reference
+
+
+
The documentation for this struct was generated from the following file:
    +
  • include/crow/middlewares/utf-8.h
  • +
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1ci__hash-members.html b/1.2/reference/structcrow_1_1ci__hash-members.html new file mode 100644 index 000000000..92bc40c1e --- /dev/null +++ b/1.2/reference/structcrow_1_1ci__hash-members.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::ci_hash Member List
+
+
+ +

This is the complete list of members for crow::ci_hash, including all inherited members.

+ + +
operator()(const std::string &key) const (defined in crow::ci_hash)crow::ci_hashinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1ci__hash.html b/1.2/reference/structcrow_1_1ci__hash.html new file mode 100644 index 000000000..97ef41c9f --- /dev/null +++ b/1.2/reference/structcrow_1_1ci__hash.html @@ -0,0 +1,137 @@ + + + + + + + + Crow: crow::ci_hash Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::ci_hash Struct Reference
+
+
+ +

Hashing function for ci_map (unordered_multimap). + More...

+ +

#include <ci_map.h>

+ + + + +

+Public Member Functions

+size_t operator() (const std::string &key) const
 
+

Detailed Description

+

Hashing function for ci_map (unordered_multimap).

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1ci__hash.js b/1.2/reference/structcrow_1_1ci__hash.js new file mode 100644 index 000000000..1782a7506 --- /dev/null +++ b/1.2/reference/structcrow_1_1ci__hash.js @@ -0,0 +1,4 @@ +var structcrow_1_1ci__hash = +[ + [ "operator()", "structcrow_1_1ci__hash.html#a9bfbe68cd9047ad7d49d26d5b704750b", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1ci__key__eq-members.html b/1.2/reference/structcrow_1_1ci__key__eq-members.html new file mode 100644 index 000000000..6c5f647ba --- /dev/null +++ b/1.2/reference/structcrow_1_1ci__key__eq-members.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::ci_key_eq Member List
+
+
+ +

This is the complete list of members for crow::ci_key_eq, including all inherited members.

+ + +
operator()(const std::string &l, const std::string &r) const (defined in crow::ci_key_eq)crow::ci_key_eqinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1ci__key__eq.html b/1.2/reference/structcrow_1_1ci__key__eq.html new file mode 100644 index 000000000..c7c3c6bac --- /dev/null +++ b/1.2/reference/structcrow_1_1ci__key__eq.html @@ -0,0 +1,137 @@ + + + + + + + + Crow: crow::ci_key_eq Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::ci_key_eq Struct Reference
+
+
+ +

Equals function for ci_map (unordered_multimap). + More...

+ +

#include <ci_map.h>

+ + + + +

+Public Member Functions

+bool operator() (const std::string &l, const std::string &r) const
 
+

Detailed Description

+

Equals function for ci_map (unordered_multimap).

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1ci__key__eq.js b/1.2/reference/structcrow_1_1ci__key__eq.js new file mode 100644 index 000000000..056f22f61 --- /dev/null +++ b/1.2/reference/structcrow_1_1ci__key__eq.js @@ -0,0 +1,4 @@ +var structcrow_1_1ci__key__eq = +[ + [ "operator()", "structcrow_1_1ci__key__eq.html#aa99476ad027288c625a8da81c301c53f", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3.html b/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3.html new file mode 100644 index 000000000..a87e343b0 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3.html @@ -0,0 +1,128 @@ + + + + + + + + Crow: crow::detail::check_after_handle_arity_3< MW > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::check_after_handle_arity_3< MW > Struct Template Reference
+
+
+ + + + +

+Classes

struct  get
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3_1_1get.html b/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3_1_1get.html new file mode 100644 index 000000000..d7f912bdb --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3_1_1get.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: crow::detail::check_after_handle_arity_3< MW >::get< T, > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::check_after_handle_arity_3< MW >::get< T, > Struct Template Reference
+
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3__const.html b/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3__const.html new file mode 100644 index 000000000..0ef5fc3c4 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3__const.html @@ -0,0 +1,128 @@ + + + + + + + + Crow: crow::detail::check_after_handle_arity_3_const< MW > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::check_after_handle_arity_3_const< MW > Struct Template Reference
+
+
+ + + + +

+Classes

struct  get
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3__const_1_1get.html b/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3__const_1_1get.html new file mode 100644 index 000000000..4c3f4a7fc --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1check__after__handle__arity__3__const_1_1get.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: crow::detail::check_after_handle_arity_3_const< MW >::get< T, const > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::check_after_handle_arity_3_const< MW >::get< T, const > Struct Template Reference
+
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3.html b/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3.html new file mode 100644 index 000000000..540f40119 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3.html @@ -0,0 +1,128 @@ + + + + + + + + Crow: crow::detail::check_before_handle_arity_3< MW > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::check_before_handle_arity_3< MW > Struct Template Reference
+
+
+ + + + +

+Classes

struct  get
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3_1_1get.html b/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3_1_1get.html new file mode 100644 index 000000000..17e89cf96 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3_1_1get.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: crow::detail::check_before_handle_arity_3< MW >::get< T, > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::check_before_handle_arity_3< MW >::get< T, > Struct Template Reference
+
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3__const.html b/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3__const.html new file mode 100644 index 000000000..ffc1a65ee --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3__const.html @@ -0,0 +1,128 @@ + + + + + + + + Crow: crow::detail::check_before_handle_arity_3_const< MW > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::check_before_handle_arity_3_const< MW > Struct Template Reference
+
+
+ + + + +

+Classes

struct  get
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3__const_1_1get.html b/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3__const_1_1get.html new file mode 100644 index 000000000..1960d4f5a --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1check__before__handle__arity__3__const_1_1get.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: crow::detail::check_before_handle_arity_3_const< MW >::get< T, const > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::check_before_handle_arity_3_const< MW >::get< T, const > Struct Template Reference
+
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1check__global__call__false.html b/1.2/reference/structcrow_1_1detail_1_1check__global__call__false.html new file mode 100644 index 000000000..7757caaee --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1check__global__call__false.html @@ -0,0 +1,128 @@ + + + + + + + + Crow: crow::detail::check_global_call_false< MW > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::check_global_call_false< MW > Struct Template Reference
+
+
+ + + + +

+Classes

struct  get
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1check__global__call__false_1_1get.html b/1.2/reference/structcrow_1_1detail_1_1check__global__call__false_1_1get.html new file mode 100644 index 000000000..61b0f43c1 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1check__global__call__false_1_1get.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: crow::detail::check_global_call_false< MW >::get< T, type > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::check_global_call_false< MW >::get< T, type > Struct Template Reference
+
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1context-members.html b/1.2/reference/structcrow_1_1detail_1_1context-members.html new file mode 100644 index 000000000..247141d40 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1context-members.html @@ -0,0 +1,124 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::context< Middlewares > Member List
+
+
+ +

This is the complete list of members for crow::detail::context< Middlewares >, including all inherited members.

+ + + + + + +
after_handlers_call_helper (defined in crow::detail::context< Middlewares >)crow::detail::context< Middlewares >friend
after_handlers_call_helper (defined in crow::detail::context< Middlewares >)crow::detail::context< Middlewares >friend
get() (defined in crow::detail::context< Middlewares >)crow::detail::context< Middlewares >inline
middleware_call_helper (defined in crow::detail::context< Middlewares >)crow::detail::context< Middlewares >friend
partial typedef (defined in crow::detail::context< Middlewares >)crow::detail::context< Middlewares >
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1context.html b/1.2/reference/structcrow_1_1detail_1_1context.html new file mode 100644 index 000000000..e1414d78c --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1context.html @@ -0,0 +1,164 @@ + + + + + + + + Crow: crow::detail::context< Middlewares > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::context< Middlewares > Struct Template Reference
+
+
+
+Inheritance diagram for crow::detail::context< Middlewares >:
+
+
+ + +crow::detail::partial_context< Middlewares... > + +
+ + + + + +

+Public Types

+template<int N>
using partial = typename partial_context< Middlewares... >::template partial< N >
 
+ + + + +

+Public Member Functions

+template<typename T >
T::context & get ()
 
+ + + + + + + + + + +

+Friends

+template<typename CallCriteria , int N, typename Context , typename Container >
std::enable_if<(N==0)>::type after_handlers_call_helper (const CallCriteria &cc, Container &middlewares, Context &ctx, request &req, response &res)
 
+template<typename CallCriteria , int N, typename Context , typename Container >
std::enable_if<(N > 0)>::type after_handlers_call_helper (const CallCriteria &cc, Container &middlewares, Context &ctx, request &req, response &res)
 
+template<typename CallCriteria , int N, typename Context , typename Container >
std::enable_if<(N< std::tuple_size< typename std::remove_reference< Container >::type >::value), bool >::type middleware_call_helper (const CallCriteria &cc, Container &middlewares, request &req, response &res, Context &ctx)
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1context.js b/1.2/reference/structcrow_1_1detail_1_1context.js new file mode 100644 index 000000000..cb90ae69d --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1context.js @@ -0,0 +1,8 @@ +var structcrow_1_1detail_1_1context = +[ + [ "partial", "structcrow_1_1detail_1_1context.html#aed24bba34e07bac2e533be71003ce1f1", null ], + [ "get", "structcrow_1_1detail_1_1context.html#a836ff37a47e92e44b7f937687bfb06e5", null ], + [ "after_handlers_call_helper", "structcrow_1_1detail_1_1context.html#a23ca581449831a76869224fa7b3075a0", null ], + [ "after_handlers_call_helper", "structcrow_1_1detail_1_1context.html#a4ff9c692bee1dd7e005f2c4a2926d621", null ], + [ "middleware_call_helper", "structcrow_1_1detail_1_1context.html#a475aca83ac34e0fe0667deb51972aaa5", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1context.png b/1.2/reference/structcrow_1_1detail_1_1context.png new file mode 100644 index 000000000..93c85353f Binary files /dev/null and b/1.2/reference/structcrow_1_1detail_1_1context.png differ diff --git a/1.2/reference/structcrow_1_1detail_1_1is__after__handle__arity__3__impl-members.html b/1.2/reference/structcrow_1_1detail_1_1is__after__handle__arity__3__impl-members.html new file mode 100644 index 000000000..2369ea7d8 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1is__after__handle__arity__3__impl-members.html @@ -0,0 +1,123 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::is_after_handle_arity_3_impl< T > Member List
+
+
+ +

This is the complete list of members for crow::detail::is_after_handle_arity_3_impl< T >, including all inherited members.

+ + + + + +
f(typename check_after_handle_arity_3_const< T >::template get< C > *) (defined in crow::detail::is_after_handle_arity_3_impl< T >)crow::detail::is_after_handle_arity_3_impl< T >static
f(typename check_after_handle_arity_3< T >::template get< C > *) (defined in crow::detail::is_after_handle_arity_3_impl< T >)crow::detail::is_after_handle_arity_3_impl< T >static
f(...) (defined in crow::detail::is_after_handle_arity_3_impl< T >)crow::detail::is_after_handle_arity_3_impl< T >static
value (defined in crow::detail::is_after_handle_arity_3_impl< T >)crow::detail::is_after_handle_arity_3_impl< T >static
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1is__after__handle__arity__3__impl.html b/1.2/reference/structcrow_1_1detail_1_1is__after__handle__arity__3__impl.html new file mode 100644 index 000000000..ebca24d4e --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1is__after__handle__arity__3__impl.html @@ -0,0 +1,146 @@ + + + + + + + + Crow: crow::detail::is_after_handle_arity_3_impl< T > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::is_after_handle_arity_3_impl< T > Struct Template Reference
+
+
+ + + + + + + + + + + +

+Static Public Member Functions

+template<typename C >
static std::true_type f (typename check_after_handle_arity_3_const< T >::template get< C > *)
 
+template<typename C >
static std::true_type f (typename check_after_handle_arity_3< T >::template get< C > *)
 
+template<typename C >
static std::false_type f (...)
 
+ + + +

+Static Public Attributes

+static constexpr bool value = decltype(f<T>(nullptr))::value
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1is__before__handle__arity__3__impl-members.html b/1.2/reference/structcrow_1_1detail_1_1is__before__handle__arity__3__impl-members.html new file mode 100644 index 000000000..15352c7c8 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1is__before__handle__arity__3__impl-members.html @@ -0,0 +1,123 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::is_before_handle_arity_3_impl< T > Member List
+
+
+ +

This is the complete list of members for crow::detail::is_before_handle_arity_3_impl< T >, including all inherited members.

+ + + + + +
f(typename check_before_handle_arity_3_const< T >::template get< C > *) (defined in crow::detail::is_before_handle_arity_3_impl< T >)crow::detail::is_before_handle_arity_3_impl< T >static
f(typename check_before_handle_arity_3< T >::template get< C > *) (defined in crow::detail::is_before_handle_arity_3_impl< T >)crow::detail::is_before_handle_arity_3_impl< T >static
f(...) (defined in crow::detail::is_before_handle_arity_3_impl< T >)crow::detail::is_before_handle_arity_3_impl< T >static
value (defined in crow::detail::is_before_handle_arity_3_impl< T >)crow::detail::is_before_handle_arity_3_impl< T >static
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1is__before__handle__arity__3__impl.html b/1.2/reference/structcrow_1_1detail_1_1is__before__handle__arity__3__impl.html new file mode 100644 index 000000000..83120e35b --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1is__before__handle__arity__3__impl.html @@ -0,0 +1,146 @@ + + + + + + + + Crow: crow::detail::is_before_handle_arity_3_impl< T > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::is_before_handle_arity_3_impl< T > Struct Template Reference
+
+
+ + + + + + + + + + + +

+Static Public Member Functions

+template<typename C >
static std::true_type f (typename check_before_handle_arity_3_const< T >::template get< C > *)
 
+template<typename C >
static std::true_type f (typename check_before_handle_arity_3< T >::template get< C > *)
 
+template<typename C >
static std::false_type f (...)
 
+ + + +

+Static Public Attributes

+static const bool value = decltype(f<T>(nullptr))::value
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1is__middleware__global-members.html b/1.2/reference/structcrow_1_1detail_1_1is__middleware__global-members.html new file mode 100644 index 000000000..f8a96a3d5 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1is__middleware__global-members.html @@ -0,0 +1,122 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::is_middleware_global< MW > Member List
+
+
+ +

This is the complete list of members for crow::detail::is_middleware_global< MW >, including all inherited members.

+ + + + +
f(typename check_global_call_false< MW >::template get< C > *) (defined in crow::detail::is_middleware_global< MW >)crow::detail::is_middleware_global< MW >static
f(...) (defined in crow::detail::is_middleware_global< MW >)crow::detail::is_middleware_global< MW >static
value (defined in crow::detail::is_middleware_global< MW >)crow::detail::is_middleware_global< MW >static
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1is__middleware__global.html b/1.2/reference/structcrow_1_1detail_1_1is__middleware__global.html new file mode 100644 index 000000000..1c378c6e6 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1is__middleware__global.html @@ -0,0 +1,142 @@ + + + + + + + + Crow: crow::detail::is_middleware_global< MW > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::is_middleware_global< MW > Struct Template Reference
+
+
+ + + + + + + + +

+Static Public Member Functions

+template<typename C >
static std::false_type f (typename check_global_call_false< MW >::template get< C > *)
 
+template<typename C >
static std::true_type f (...)
 
+ + + +

+Static Public Attributes

+static const bool value = decltype(f<MW>(nullptr))::value
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic.html b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic.html new file mode 100644 index 000000000..30095b4da --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: crow::detail::middleware_call_criteria_dynamic< Reversed > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::middleware_call_criteria_dynamic< Reversed > Struct Template Reference
+
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4-members.html b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4-members.html new file mode 100644 index 000000000..d611b15b6 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4-members.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::middleware_call_criteria_dynamic< false > Member List
+
+
+ +

This is the complete list of members for crow::detail::middleware_call_criteria_dynamic< false >, including all inherited members.

+ + + +
enabled(int mw_index) const (defined in crow::detail::middleware_call_criteria_dynamic< false >)crow::detail::middleware_call_criteria_dynamic< false >inline
middleware_call_criteria_dynamic(const std::vector< int > &indices) (defined in crow::detail::middleware_call_criteria_dynamic< false >)crow::detail::middleware_call_criteria_dynamic< false >inline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.html b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.html new file mode 100644 index 000000000..cb61d2183 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.html @@ -0,0 +1,134 @@ + + + + + + + + Crow: crow::detail::middleware_call_criteria_dynamic< false > Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::middleware_call_criteria_dynamic< false > Struct Reference
+
+
+ + + + + + + +

+Public Member Functions

middleware_call_criteria_dynamic (const std::vector< int > &indices)
 
+template<typename >
bool enabled (int mw_index) const
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.js b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.js new file mode 100644 index 000000000..9b1518b62 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.js @@ -0,0 +1,5 @@ +var structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4 = +[ + [ "middleware_call_criteria_dynamic", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.html#a975e9db833b37965e9113a44787de713", null ], + [ "enabled", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01false_01_4.html#a03d8f77d9bec07bf6cddce95adde8fc6", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4-members.html b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4-members.html new file mode 100644 index 000000000..2386297fc --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4-members.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::middleware_call_criteria_dynamic< true > Member List
+
+
+ +

This is the complete list of members for crow::detail::middleware_call_criteria_dynamic< true >, including all inherited members.

+ + + +
enabled(int mw_index) const (defined in crow::detail::middleware_call_criteria_dynamic< true >)crow::detail::middleware_call_criteria_dynamic< true >inline
middleware_call_criteria_dynamic(const std::vector< int > &indices) (defined in crow::detail::middleware_call_criteria_dynamic< true >)crow::detail::middleware_call_criteria_dynamic< true >inline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.html b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.html new file mode 100644 index 000000000..9a3f7fe4f --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.html @@ -0,0 +1,134 @@ + + + + + + + + Crow: crow::detail::middleware_call_criteria_dynamic< true > Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::middleware_call_criteria_dynamic< true > Struct Reference
+
+
+ + + + + + + +

+Public Member Functions

middleware_call_criteria_dynamic (const std::vector< int > &indices)
 
+template<typename >
bool enabled (int mw_index) const
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.js b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.js new file mode 100644 index 000000000..3dae86386 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.js @@ -0,0 +1,5 @@ +var structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4 = +[ + [ "middleware_call_criteria_dynamic", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.html#a6f5d720273c0de6ae01a138e0bb84cc6", null ], + [ "enabled", "structcrow_1_1detail_1_1middleware__call__criteria__dynamic_3_01true_01_4.html#abf5e13ed2e5057951fffb0ffa4c41ad5", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__only__global-members.html b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__only__global-members.html new file mode 100644 index 000000000..0f4a17fc7 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__only__global-members.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::middleware_call_criteria_only_global Member List
+
+
+ +

This is the complete list of members for crow::detail::middleware_call_criteria_only_global, including all inherited members.

+ + +
enabled(int) const (defined in crow::detail::middleware_call_criteria_only_global)crow::detail::middleware_call_criteria_only_globalinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__only__global.html b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__only__global.html new file mode 100644 index 000000000..8b491ff16 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__only__global.html @@ -0,0 +1,131 @@ + + + + + + + + Crow: crow::detail::middleware_call_criteria_only_global Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::middleware_call_criteria_only_global Struct Reference
+
+
+ + + + + +

+Public Member Functions

+template<typename MW >
constexpr bool enabled (int) const
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__only__global.js b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__only__global.js new file mode 100644 index 000000000..df0fb3796 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__call__criteria__only__global.js @@ -0,0 +1,4 @@ +var structcrow_1_1detail_1_1middleware__call__criteria__only__global = +[ + [ "enabled", "structcrow_1_1detail_1_1middleware__call__criteria__only__global.html#a9f2185f986461f1c1cdc0e808107a0fe", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__indices-members.html b/1.2/reference/structcrow_1_1detail_1_1middleware__indices-members.html new file mode 100644 index 000000000..5b26001db --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__indices-members.html @@ -0,0 +1,127 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::middleware_indices Member List
+
+
+ +

This is the complete list of members for crow::detail::middleware_indices, including all inherited members.

+ + + + + + + + + +
empty() const (defined in crow::detail::middleware_indices)crow::detail::middleware_indicesinline
indices() (defined in crow::detail::middleware_indices)crow::detail::middleware_indicesinline
merge_back(const detail::middleware_indices &other) (defined in crow::detail::middleware_indices)crow::detail::middleware_indicesinline
merge_front(const detail::middleware_indices &other) (defined in crow::detail::middleware_indices)crow::detail::middleware_indicesinline
pack() (defined in crow::detail::middleware_indices)crow::detail::middleware_indicesinline
pop_back(const detail::middleware_indices &other) (defined in crow::detail::middleware_indices)crow::detail::middleware_indicesinline
push() (defined in crow::detail::middleware_indices)crow::detail::middleware_indicesinline
push() (defined in crow::detail::middleware_indices)crow::detail::middleware_indicesinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__indices.html b/1.2/reference/structcrow_1_1detail_1_1middleware__indices.html new file mode 100644 index 000000000..7641ac0fe --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__indices.html @@ -0,0 +1,160 @@ + + + + + + + + Crow: crow::detail::middleware_indices Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::middleware_indices Struct Reference
+
+
+ +

Typesafe wrapper for storing lists of middleware as their indices in the App. + More...

+ +

#include <routing.h>

+ + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

+template<typename App >
void push ()
 
+template<typename App , typename MW , typename... Middlewares>
void push ()
 
+void merge_front (const detail::middleware_indices &other)
 
+void merge_back (const detail::middleware_indices &other)
 
+void pop_back (const detail::middleware_indices &other)
 
+bool empty () const
 
+void pack ()
 
+const std::vector< int > & indices ()
 
+

Detailed Description

+

Typesafe wrapper for storing lists of middleware as their indices in the App.

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1middleware__indices.js b/1.2/reference/structcrow_1_1detail_1_1middleware__indices.js new file mode 100644 index 000000000..f571c2678 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1middleware__indices.js @@ -0,0 +1,11 @@ +var structcrow_1_1detail_1_1middleware__indices = +[ + [ "empty", "structcrow_1_1detail_1_1middleware__indices.html#aad27a0ce958bb8e27745074c981343bf", null ], + [ "indices", "structcrow_1_1detail_1_1middleware__indices.html#af39a30d7ee959d091ff54ffe7cb0c953", null ], + [ "merge_back", "structcrow_1_1detail_1_1middleware__indices.html#a3c23c2fd745612f1f126b63fbec1a547", null ], + [ "merge_front", "structcrow_1_1detail_1_1middleware__indices.html#ad18f7bb499a4f6f7164a9c606e6139eb", null ], + [ "pack", "structcrow_1_1detail_1_1middleware__indices.html#a651af159fea3392c2df7e7146079ad8e", null ], + [ "pop_back", "structcrow_1_1detail_1_1middleware__indices.html#acb908d4e9aa55225ff3e9f7de9463977", null ], + [ "push", "structcrow_1_1detail_1_1middleware__indices.html#a539f94cc6a5bc5a34e1b04bca251b06e", null ], + [ "push", "structcrow_1_1detail_1_1middleware__indices.html#a736f04d2df37ccbee5650f58fb36d4fc", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1partial__context-members.html b/1.2/reference/structcrow_1_1detail_1_1partial__context-members.html new file mode 100644 index 000000000..f653acc03 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1partial__context-members.html @@ -0,0 +1,122 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::partial_context< Middlewares > Member List
+
+ +
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1partial__context.html b/1.2/reference/structcrow_1_1detail_1_1partial__context.html new file mode 100644 index 000000000..173c01925 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1partial__context.html @@ -0,0 +1,148 @@ + + + + + + + + Crow: crow::detail::partial_context< Middlewares > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::partial_context< Middlewares > Struct Template Reference
+
+
+
+Inheritance diagram for crow::detail::partial_context< Middlewares >:
+
+
+ +
+ + + + + + + +

+Public Types

+using parent_context = typename black_magic::pop_back< Middlewares... >::template rebind<::crow::detail::partial_context >
 
+template<int N>
using partial = typename std::conditional< N==sizeof...(Middlewares) - 1, partial_context, typename parent_context::template partial< N > >::type
 
+ + + + +

+Public Member Functions

+template<typename T >
T::context & get ()
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1partial__context.js b/1.2/reference/structcrow_1_1detail_1_1partial__context.js new file mode 100644 index 000000000..86a27345a --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1partial__context.js @@ -0,0 +1,6 @@ +var structcrow_1_1detail_1_1partial__context = +[ + [ "parent_context", "structcrow_1_1detail_1_1partial__context.html#a96e8bff131568e0e6ecffd75b5b29e09", null ], + [ "partial", "structcrow_1_1detail_1_1partial__context.html#a03e97f4c19ad975765f09af6e097ca46", null ], + [ "get", "structcrow_1_1detail_1_1partial__context.html#ac787877fdf379960d15067f2bc526850", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1partial__context.png b/1.2/reference/structcrow_1_1detail_1_1partial__context.png new file mode 100644 index 000000000..f981dc60c Binary files /dev/null and b/1.2/reference/structcrow_1_1detail_1_1partial__context.png differ diff --git a/1.2/reference/structcrow_1_1detail_1_1partial__context_3_4-members.html b/1.2/reference/structcrow_1_1detail_1_1partial__context_3_4-members.html new file mode 100644 index 000000000..ff50f4e29 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1partial__context_3_4-members.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::partial_context<> Member List
+
+
+ +

This is the complete list of members for crow::detail::partial_context<>, including all inherited members.

+ + +
partial typedef (defined in crow::detail::partial_context<>)crow::detail::partial_context<>
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1partial__context_3_4.html b/1.2/reference/structcrow_1_1detail_1_1partial__context_3_4.html new file mode 100644 index 000000000..54a5da549 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1partial__context_3_4.html @@ -0,0 +1,131 @@ + + + + + + + + Crow: crow::detail::partial_context<> Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::partial_context<> Struct Reference
+
+
+ + + + + +

+Public Types

+template<int >
using partial = partial_context
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1partial__context_3_4.js b/1.2/reference/structcrow_1_1detail_1_1partial__context_3_4.js new file mode 100644 index 000000000..48f8f5957 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1partial__context_3_4.js @@ -0,0 +1,4 @@ +var structcrow_1_1detail_1_1partial__context_3_4 = +[ + [ "partial", "structcrow_1_1detail_1_1partial__context_3_4.html#a4c2945874debb1b522dd6f81ee5b7865", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped-members.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped-members.html new file mode 100644 index 000000000..8880829a3 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped-members.html @@ -0,0 +1,124 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped > Member List
+
+
+ +

This is the complete list of members for crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >, including all inherited members.

+ + + + + + +
handler_ (defined in crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >)crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >
operator()(request &req, response &res, const routing_params &params) (defined in crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >)crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >inline
set_(Func f, typename std::enable_if<!std::is_same< typename std::tuple_element< 0, std::tuple< Args..., void >>::type, const request & >::value, int >::type=0) (defined in crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >)crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >inline
set_(Func f, typename std::enable_if< std::is_same< typename std::tuple_element< 0, std::tuple< Args..., void >>::type, const request & >::value &&!std::is_same< typename std::tuple_element< 1, std::tuple< Args..., void, void >>::type, response & >::value, int >::type=0) (defined in crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >)crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >inline
set_(Func f, typename std::enable_if< std::is_same< typename std::tuple_element< 0, std::tuple< Args..., void >>::type, const request & >::value &&std::is_same< typename std::tuple_element< 1, std::tuple< Args..., void, void >>::type, response & >::value, int >::type=0) (defined in crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >)crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >inline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html new file mode 100644 index 000000000..f519893a0 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html @@ -0,0 +1,161 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped > Struct Template Reference
+
+
+ + + + + + + + + + +

+Classes

struct  handler_type_helper
 
struct  handler_type_helper< const request &, Args... >
 
struct  handler_type_helper< const request &, response &, Args... >
 
struct  req_handler_wrapper
 
+ + + + + + + + + + + + +

+Public Member Functions

+template<typename... Args>
void set_ (Func f, typename std::enable_if<!std::is_same< typename std::tuple_element< 0, std::tuple< Args..., void >>::type, const request & >::value, int >::type=0)
 
+template<typename... Args>
void set_ (Func f, typename std::enable_if< std::is_same< typename std::tuple_element< 0, std::tuple< Args..., void >>::type, const request & >::value &&!std::is_same< typename std::tuple_element< 1, std::tuple< Args..., void, void >>::type, response & >::value, int >::type=0)
 
+template<typename... Args>
void set_ (Func f, typename std::enable_if< std::is_same< typename std::tuple_element< 0, std::tuple< Args..., void >>::type, const request & >::value &&std::is_same< typename std::tuple_element< 1, std::tuple< Args..., void, void >>::type, response & >::value, int >::type=0)
 
+void operator() (request &req, response &res, const routing_params &params)
 
+ + + +

+Public Attributes

+handler_type_helper< ArgsWrapped... >::type handler_
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.js new file mode 100644 index 000000000..0fa5678cd --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.js @@ -0,0 +1,12 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped = +[ + [ "handler_type_helper", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper" ], + [ "handler_type_helper< const request &, Args... >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36" ], + [ "handler_type_helper< const request &, response &, Args... >", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a" ], + [ "req_handler_wrapper", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.html", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper" ], + [ "operator()", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html#a7c6cb901c6ee98bc70ee42fe26b1e404", null ], + [ "set_", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html#ac0b5953ef5f2de56e33b46c0b2d53d11", null ], + [ "set_", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html#adb1db474bf72cfc2e4b2f8572dd83286", null ], + [ "set_", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html#a7f3fd6ee05bf001b80694565fa1d3439", null ], + [ "handler_", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped.html#ab8030d2b00c5a3f90c269423e1d26efe", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper-members.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper-members.html new file mode 100644 index 000000000..ac052deb7 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper-members.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ + + + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html new file mode 100644 index 000000000..13b5ec833 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html @@ -0,0 +1,133 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< Args > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< Args > Struct Template Reference
+
+
+ + + + + + +

+Public Types

+using type = std::function< void(const crow::request &, crow::response &, Args...)>
 
+using args_type = black_magic::S< typename black_magic::promote_t< Args >... >
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.js new file mode 100644 index 000000000..703919920 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.js @@ -0,0 +1,5 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper = +[ + [ "args_type", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html#a9914a4b757ed58f4a938a45b26774055", null ], + [ "type", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper.html#a4c2a9a1065506309bd9b8a37d6518e3e", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.html new file mode 100644 index 000000000..6934b4161 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.html @@ -0,0 +1,133 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< const request &, Args... > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< const request &, Args... > Struct Template Reference
+
+
+ + + + + + +

+Public Types

+using type = std::function< void(const crow::request &, crow::response &, Args...)>
 
+using args_type = black_magic::S< typename black_magic::promote_t< Args >... >
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.js new file mode 100644 index 000000000..f7577bf03 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.js @@ -0,0 +1,5 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36 = +[ + [ "args_type", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.html#a9d7e8d0b0ee47af5b45064956e3d695d", null ], + [ "type", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_012f01fc0d25e96ed100e3017a66fd4b36.html#a4b9a993c5bb83893aa7f4fcc4bd159ba", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_0186971087dc8233b0c92d7933c39bf610.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_0186971087dc8233b0c92d7933c39bf610.html new file mode 100644 index 000000000..9d0f38745 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_0186971087dc8233b0c92d7933c39bf610.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ + + + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.html new file mode 100644 index 000000000..d2a14b7d5 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.html @@ -0,0 +1,133 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< const request &, response &, Args... > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::handler_type_helper< const request &, response &, Args... > Struct Template Reference
+
+
+ + + + + + +

+Public Types

+using type = std::function< void(const crow::request &, crow::response &, Args...)>
 
+using args_type = black_magic::S< typename black_magic::promote_t< Args >... >
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.js new file mode 100644 index 000000000..1af6d9120 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.js @@ -0,0 +1,5 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a = +[ + [ "args_type", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.html#a1ed6dda811a1c1a53a38502aa816f342", null ], + [ "type", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01e78e01f0ab35f7c7c9ae99998f83560a.html#aa9221a71167d40ff603f92ea8232fecd", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01f08049deec6764f7b8eb3fe2826503a3.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01f08049deec6764f7b8eb3fe2826503a3.html new file mode 100644 index 000000000..fd467de8b --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1handler__type__helper_3_01f08049deec6764f7b8eb3fe2826503a3.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ + + + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper-members.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper-members.html new file mode 100644 index 000000000..19810e2ea --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper-members.html @@ -0,0 +1,122 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ + + + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.html new file mode 100644 index 000000000..68346034a --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.html @@ -0,0 +1,140 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::req_handler_wrapper< Req, Args > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::Wrapped< Func, ArgsWrapped >::req_handler_wrapper< Req, Args > Struct Template Reference
+
+
+ + + + + + +

+Public Member Functions

req_handler_wrapper (Func f)
 
+void operator() (const request &req, response &res, Args... args)
 
+ + + +

+Public Attributes

+Func f
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.js new file mode 100644 index 000000000..ea86183eb --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.js @@ -0,0 +1,6 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper = +[ + [ "req_handler_wrapper", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.html#aba29fdf5c44192709c4eef8e84a48485", null ], + [ "operator()", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.html#a40965565a28cc879ec75c831c0b729ae", null ], + [ "f", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1_wrapped_1_1req__handler__wrapper.html#a0553c3d38f4902d9c3fa8655812ddbd7", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call.html new file mode 100644 index 000000000..9ae772b16 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, S1, S2 > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, S1, S2 > Struct Template Reference
+
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_009b04635dc3ea351c7ce5dd2e3426faa.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_009b04635dc3ea351c7ce5dd2e3426faa.html new file mode 100644 index 000000000..a338acc7f --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_009b04635dc3ea351c7ce5dd2e3426faa.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S< Args1... > > Member List
+
+ +
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.html new file mode 100644 index 000000000..909409e10 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.html @@ -0,0 +1,130 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< uint64_t, Args1... >, black_magic::S< Args2... > > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< uint64_t, Args1... >, black_magic::S< Args2... > > Struct Template Reference
+
+
+ + + + +

+Public Member Functions

+void operator() (F cparams)
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.js new file mode 100644 index 000000000..1b42622e3 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.js @@ -0,0 +1,4 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef = +[ + [ "operator()", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_00f79d82c7e7da7530b290964906e13ef.html#abaa2c6f8c915c89eccd1c46e6526f359", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.html new file mode 100644 index 000000000..965698851 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.html @@ -0,0 +1,130 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S< Args1... > > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S< Args1... > > Struct Template Reference
+
+
+ + + + +

+Public Member Functions

+void operator() (F cparams)
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.js new file mode 100644 index 000000000..0675f5365 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.js @@ -0,0 +1,4 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8 = +[ + [ "operator()", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_019b104fb9907823e3e218e8e95ffa9c8.html#aee7a6bfbe87eb8ebf9667a5e83f55e5c", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_03cbee875097fe0cad879d3a4da5667f2.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_03cbee875097fe0cad879d3a4da5667f2.html new file mode 100644 index 000000000..1442e0fea --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_03cbee875097fe0cad879d3a4da5667f2.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< double, Args1... >, black_magic::S< Args2... > > Member List
+
+ +
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_06661c8ea83d528496c47263f48427c57.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_06661c8ea83d528496c47263f48427c57.html new file mode 100644 index 000000000..81666cc85 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_06661c8ea83d528496c47263f48427c57.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< std::string, Args1... >, black_magic::S< Args2... > > Member List
+
+ +
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0680c9ce998dbf1887c61613a0545948f.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0680c9ce998dbf1887c61613a0545948f.html new file mode 100644 index 000000000..124212513 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0680c9ce998dbf1887c61613a0545948f.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< uint64_t, Args1... >, black_magic::S< Args2... > > Member List
+
+ +
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.html new file mode 100644 index 000000000..f378cf03c --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.html @@ -0,0 +1,130 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< double, Args1... >, black_magic::S< Args2... > > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< double, Args1... >, black_magic::S< Args2... > > Struct Template Reference
+
+
+ + + + +

+Public Member Functions

+void operator() (F cparams)
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.js new file mode 100644 index 000000000..95d993bdf --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.js @@ -0,0 +1,4 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5 = +[ + [ "operator()", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0ac50968f63df9484eeaa96bf94c67fc5.html#a110cd27d7795734b30bfd723573c1a5f", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.html new file mode 100644 index 000000000..cbccbc829 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.html @@ -0,0 +1,130 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< int64_t, Args1... >, black_magic::S< Args2... > > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< int64_t, Args1... >, black_magic::S< Args2... > > Struct Template Reference
+
+
+ + + + +

+Public Member Functions

+void operator() (F cparams)
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.js new file mode 100644 index 000000000..4b43d3130 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.js @@ -0,0 +1,4 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4 = +[ + [ "operator()", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0b63d09427b176e92959de8d063124ae4.html#a238a40bdff8c5cefe74274551b993c9c", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0e1b8b4699f9e8186868ddd3c96e49126.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0e1b8b4699f9e8186868ddd3c96e49126.html new file mode 100644 index 000000000..3a593401f --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0e1b8b4699f9e8186868ddd3c96e49126.html @@ -0,0 +1,120 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< int64_t, Args1... >, black_magic::S< Args2... > > Member List
+
+ +
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.html new file mode 100644 index 000000000..f0190ab73 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.html @@ -0,0 +1,130 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< std::string, Args1... >, black_magic::S< Args2... > > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::call< F, NInt, NUint, NDouble, NString, black_magic::S< std::string, Args1... >, black_magic::S< Args2... > > Struct Template Reference
+
+
+ + + + +

+Public Member Functions

+void operator() (F cparams)
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.js new file mode 100644 index 000000000..8fbe352a4 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.js @@ -0,0 +1,4 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4 = +[ + [ "operator()", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call_3_01_f_00_01_n_int_00_01_n_uint_0eca3da881de1118eaf3d106d8d88f2d4.html#af7b27a90d5a598b841c0fc0af3f9d7bf", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair-members.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair-members.html new file mode 100644 index 000000000..cadde251b --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair-members.html @@ -0,0 +1,121 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::detail::routing_handler_call_helper::call_pair< T, Pos > Member List
+
+ +
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.html new file mode 100644 index 000000000..a9da5cf55 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.html @@ -0,0 +1,137 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::call_pair< T, Pos > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::call_pair< T, Pos > Struct Template Reference
+
+
+ + + + +

+Public Types

+using type = T
 
+ + + +

+Static Public Attributes

+static const int pos = Pos
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.js new file mode 100644 index 000000000..6a96a6d4d --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.js @@ -0,0 +1,4 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair = +[ + [ "type", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__pair.html#ac9c6c2efb5d7d0360e8950a314b336c5", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params-members.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params-members.html new file mode 100644 index 000000000..1bd8a18c2 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params-members.html @@ -0,0 +1,123 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ + + + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html new file mode 100644 index 000000000..efaaab75b --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html @@ -0,0 +1,139 @@ + + + + + + + + Crow: crow::detail::routing_handler_call_helper::call_params< H1 > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::detail::routing_handler_call_helper::call_params< H1 > Struct Template Reference
+
+
+ + + + + + + + + + +

+Public Attributes

+H1 & handler
 
+const routing_params & params
 
+requestreq
 
+responseres
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.js b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.js new file mode 100644 index 000000000..4d94d9f08 --- /dev/null +++ b/1.2/reference/structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.js @@ -0,0 +1,7 @@ +var structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params = +[ + [ "handler", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html#a4ce1d7e1b3b191aaaea19bbc3ad61e0d", null ], + [ "params", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html#a3e6c2066cd82b91d35550db36513d4bc", null ], + [ "req", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html#a3b2d260f66b618ea4bf7f75f0bd739e1", null ], + [ "res", "structcrow_1_1detail_1_1routing__handler__call__helper_1_1call__params.html#ad63d6c1902dab21178b1b2644ec0d407", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1http__parser-members.html b/1.2/reference/structcrow_1_1http__parser-members.html new file mode 100644 index 000000000..902f51fab --- /dev/null +++ b/1.2/reference/structcrow_1_1http__parser-members.html @@ -0,0 +1,135 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::http_parser Member List
+
+
+ +

This is the complete list of members for crow::http_parser, including all inherited members.

+ + + + + + + + + + + + + + + + + +
allow_chunked_length (defined in crow::http_parser)crow::http_parser
content_length (defined in crow::http_parser)crow::http_parser
datacrow::http_parser
flagscrow::http_parser
header_state (defined in crow::http_parser)crow::http_parser
http_errno (defined in crow::http_parser)crow::http_parser
http_majorcrow::http_parser
http_minor (defined in crow::http_parser)crow::http_parser
index (defined in crow::http_parser)crow::http_parser
lenient_http_headers (defined in crow::http_parser)crow::http_parser
method (defined in crow::http_parser)crow::http_parser
nread (defined in crow::http_parser)crow::http_parser
qs_point (defined in crow::http_parser)crow::http_parser
state (defined in crow::http_parser)crow::http_parser
upgrade (defined in crow::http_parser)crow::http_parser
uses_transfer_encoding (defined in crow::http_parser)crow::http_parser
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1http__parser.html b/1.2/reference/structcrow_1_1http__parser.html new file mode 100644 index 000000000..326fa8b06 --- /dev/null +++ b/1.2/reference/structcrow_1_1http__parser.html @@ -0,0 +1,228 @@ + + + + + + + + Crow: crow::http_parser Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::http_parser Struct Reference
+
+
+
+Inheritance diagram for crow::http_parser:
+
+
+ + +crow::HTTPParser< crow::Connection > +crow::HTTPParser< Handler > + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Attributes

unsigned int flags: 7
 
+unsigned int state: 8
 
+unsigned int header_state: 7
 
+unsigned int index: 5
 
+unsigned int uses_transfer_encoding: 1
 
+unsigned int allow_chunked_length: 1
 
+unsigned int lenient_http_headers: 1
 
+uint32_t nread
 
+uint64_t content_length
 
+unsigned long qs_point
 
unsigned char http_major
 
+unsigned char http_minor
 
+unsigned int method: 8
 
+unsigned int http_errno: 7
 
+unsigned int upgrade: 1
 
void * data
 
+

Member Data Documentation

+ +

◆ data

+ +
+
+ + + + +
void* crow::http_parser::data
+
+

PUBLIC

+ +
+
+ +

◆ flags

+ +
+
+ + + + +
unsigned int crow::http_parser::flags
+
+

PRIVATE

+ +
+
+ +

◆ http_major

+ +
+
+ + + + +
unsigned char crow::http_parser::http_major
+
+

READ-ONLY

+ +
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1http__parser.js b/1.2/reference/structcrow_1_1http__parser.js new file mode 100644 index 000000000..6654120c0 --- /dev/null +++ b/1.2/reference/structcrow_1_1http__parser.js @@ -0,0 +1,19 @@ +var structcrow_1_1http__parser = +[ + [ "allow_chunked_length", "structcrow_1_1http__parser.html#a750fbd59d9c7ea5a3587e8d5f61d84fa", null ], + [ "content_length", "structcrow_1_1http__parser.html#a6b8fe43fd3be8c425ef76a0990245914", null ], + [ "data", "structcrow_1_1http__parser.html#ac110503546750f343ad176dea0f48aa0", null ], + [ "flags", "structcrow_1_1http__parser.html#ab05c7677ce9af6c659e4401bb24484e7", null ], + [ "header_state", "structcrow_1_1http__parser.html#ad3b14a2b041d79a428e84323a0565510", null ], + [ "http_errno", "structcrow_1_1http__parser.html#a449d1c1821c1758b82cb4628ac5b47a3", null ], + [ "http_major", "structcrow_1_1http__parser.html#a6f9afc90d7c8557570973524e41fc299", null ], + [ "http_minor", "structcrow_1_1http__parser.html#a2e9238ad152183eb4c18b2ca33d9876f", null ], + [ "index", "structcrow_1_1http__parser.html#a965bf8f2aad3dc9b34fa82f1805a5fd4", null ], + [ "lenient_http_headers", "structcrow_1_1http__parser.html#a4319f3554587e1a0c6ad22a091128323", null ], + [ "method", "structcrow_1_1http__parser.html#ad76b58bd54d3869f15f795a44e38f362", null ], + [ "nread", "structcrow_1_1http__parser.html#a3f75f96b5dae11f0917323612a8a6e6d", null ], + [ "qs_point", "structcrow_1_1http__parser.html#ae2716b7c09d604478000e27bfe83b07a", null ], + [ "state", "structcrow_1_1http__parser.html#a73ccef5e9e46e73c4f52b3cd3459d68a", null ], + [ "upgrade", "structcrow_1_1http__parser.html#a246efd035f2914e1ff4f134b8c92978c", null ], + [ "uses_transfer_encoding", "structcrow_1_1http__parser.html#ab1189de2151d45afdbe7a41ed90a0019", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1http__parser.png b/1.2/reference/structcrow_1_1http__parser.png new file mode 100644 index 000000000..1020d01e9 Binary files /dev/null and b/1.2/reference/structcrow_1_1http__parser.png differ diff --git a/1.2/reference/structcrow_1_1http__parser__settings-members.html b/1.2/reference/structcrow_1_1http__parser__settings-members.html new file mode 100644 index 000000000..123d1b016 --- /dev/null +++ b/1.2/reference/structcrow_1_1http__parser__settings-members.html @@ -0,0 +1,127 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::http_parser_settings Member List
+
+
+ +

This is the complete list of members for crow::http_parser_settings, including all inherited members.

+ + + + + + + + + +
on_body (defined in crow::http_parser_settings)crow::http_parser_settings
on_header_field (defined in crow::http_parser_settings)crow::http_parser_settings
on_header_value (defined in crow::http_parser_settings)crow::http_parser_settings
on_headers_complete (defined in crow::http_parser_settings)crow::http_parser_settings
on_message_begin (defined in crow::http_parser_settings)crow::http_parser_settings
on_message_complete (defined in crow::http_parser_settings)crow::http_parser_settings
on_method (defined in crow::http_parser_settings)crow::http_parser_settings
on_url (defined in crow::http_parser_settings)crow::http_parser_settings
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1http__parser__settings.html b/1.2/reference/structcrow_1_1http__parser__settings.html new file mode 100644 index 000000000..b1a366369 --- /dev/null +++ b/1.2/reference/structcrow_1_1http__parser__settings.html @@ -0,0 +1,151 @@ + + + + + + + + Crow: crow::http_parser_settings Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::http_parser_settings Struct Reference
+
+
+ + + + + + + + + + + + + + + + + + +

+Public Attributes

+http_cb on_message_begin
 
+http_cb on_method
 
+http_data_cb on_url
 
+http_data_cb on_header_field
 
+http_data_cb on_header_value
 
+http_cb on_headers_complete
 
+http_data_cb on_body
 
+http_cb on_message_complete
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1http__parser__settings.js b/1.2/reference/structcrow_1_1http__parser__settings.js new file mode 100644 index 000000000..eb7edd025 --- /dev/null +++ b/1.2/reference/structcrow_1_1http__parser__settings.js @@ -0,0 +1,11 @@ +var structcrow_1_1http__parser__settings = +[ + [ "on_body", "structcrow_1_1http__parser__settings.html#a20b07477f3fe59d7a21661130ec8e412", null ], + [ "on_header_field", "structcrow_1_1http__parser__settings.html#a286193f56981d6a25beb61abe3bb8976", null ], + [ "on_header_value", "structcrow_1_1http__parser__settings.html#a9ebc9da224ae6fd8c764beba927f7a0f", null ], + [ "on_headers_complete", "structcrow_1_1http__parser__settings.html#adf6a842bf5139a96eff50819b5adccf1", null ], + [ "on_message_begin", "structcrow_1_1http__parser__settings.html#ad11e64eb39d166c3308e04ce98bd2d95", null ], + [ "on_message_complete", "structcrow_1_1http__parser__settings.html#a84d16c5f3b2eec79ad197b2c0ded2443", null ], + [ "on_method", "structcrow_1_1http__parser__settings.html#a49d98a61b5cc5661a44b61015ba2ea26", null ], + [ "on_url", "structcrow_1_1http__parser__settings.html#a3fe55aa616e1e4d869ba263b5e644dfb", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1json_1_1detail_1_1r__string-members.html b/1.2/reference/structcrow_1_1json_1_1detail_1_1r__string-members.html new file mode 100644 index 000000000..4225e0c13 --- /dev/null +++ b/1.2/reference/structcrow_1_1json_1_1detail_1_1r__string-members.html @@ -0,0 +1,140 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::json::detail::r_string Member List
+
+
+ +

This is the complete list of members for crow::json::detail::r_string, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + +
begin() const (defined in crow::json::detail::r_string)crow::json::detail::r_stringinline
const_iterator typedef (defined in crow::json::detail::r_string)crow::json::detail::r_string
crow::json::load (defined in crow::json::detail::r_string)crow::json::detail::r_stringfriend
e_crow::json::detail::r_stringmutable
end() const (defined in crow::json::detail::r_string)crow::json::detail::r_stringinline
iterator typedef (defined in crow::json::detail::r_string)crow::json::detail::r_string
operator std::string() const (defined in crow::json::detail::r_string)crow::json::detail::r_stringinline
operator<< (defined in crow::json::detail::r_string)crow::json::detail::r_stringfriend
operator=(r_string &&r) (defined in crow::json::detail::r_string)crow::json::detail::r_stringinline
operator=(const r_string &r) (defined in crow::json::detail::r_string)crow::json::detail::r_stringinline
operator== (defined in crow::json::detail::r_string)crow::json::detail::r_stringfriend
operator== (defined in crow::json::detail::r_string)crow::json::detail::r_stringfriend
operator== (defined in crow::json::detail::r_string)crow::json::detail::r_stringfriend
owned_ (defined in crow::json::detail::r_string)crow::json::detail::r_string
r_string() (defined in crow::json::detail::r_string)crow::json::detail::r_stringinline
r_string(char *s, char *e) (defined in crow::json::detail::r_string)crow::json::detail::r_stringinline
r_string(const r_string &r) (defined in crow::json::detail::r_string)crow::json::detail::r_stringinline
r_string(r_string &&r) (defined in crow::json::detail::r_string)crow::json::detail::r_stringinline
s_crow::json::detail::r_string
size() const (defined in crow::json::detail::r_string)crow::json::detail::r_stringinline
~r_string() (defined in crow::json::detail::r_string)crow::json::detail::r_stringinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1json_1_1detail_1_1r__string.html b/1.2/reference/structcrow_1_1json_1_1detail_1_1r__string.html new file mode 100644 index 000000000..c50ead5df --- /dev/null +++ b/1.2/reference/structcrow_1_1json_1_1detail_1_1r__string.html @@ -0,0 +1,205 @@ + + + + + + + + Crow: crow::json::detail::r_string Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::json::detail::r_string Struct Reference
+
+
+ +

A read string implementation with comparison functionality. + More...

+ +

#include <json.h>

+ + + + + + +

+Public Types

+using iterator = const char *
 
+using const_iterator = const char *
 
+ + + + + + + + + + + + + + + + + + + +

+Public Member Functions

r_string (char *s, char *e)
 
r_string (const r_string &r)
 
r_string (r_string &&r)
 
+r_stringoperator= (r_string &&r)
 
+r_stringoperator= (const r_string &r)
 
operator std::string () const
 
+const char * begin () const
 
+const char * end () const
 
+size_t size () const
 
+ + + + + + + + + +

+Public Attributes

+char * s_
 Start.
 
+char * e_
 End.
 
+uint8_t owned_ {0}
 
+ + + + + + + + + + + +

+Friends

+std::ostream & operator<< (std::ostream &os, const r_string &s)
 
+rvalue crow::json::load (const char *data, size_t size)
 
+bool operator== (const r_string &l, const r_string &r)
 
+bool operator== (const std::string &l, const r_string &r)
 
+bool operator== (const r_string &l, const std::string &r)
 
+

Detailed Description

+

A read string implementation with comparison functionality.

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1json_1_1detail_1_1r__string.js b/1.2/reference/structcrow_1_1json_1_1detail_1_1r__string.js new file mode 100644 index 000000000..817903ad9 --- /dev/null +++ b/1.2/reference/structcrow_1_1json_1_1detail_1_1r__string.js @@ -0,0 +1,24 @@ +var structcrow_1_1json_1_1detail_1_1r__string = +[ + [ "const_iterator", "structcrow_1_1json_1_1detail_1_1r__string.html#a7efeef8e8e48862b18217693ac68529d", null ], + [ "iterator", "structcrow_1_1json_1_1detail_1_1r__string.html#a3f1edea7d37fb9b1ae6b348787e3026f", null ], + [ "r_string", "structcrow_1_1json_1_1detail_1_1r__string.html#a2223afe7a9d4374a25b87495cc857eaa", null ], + [ "r_string", "structcrow_1_1json_1_1detail_1_1r__string.html#a83781200bd2f4a7547e776f14e6a7568", null ], + [ "~r_string", "structcrow_1_1json_1_1detail_1_1r__string.html#a7d91b49b42653bc18a8c03d666d705af", null ], + [ "r_string", "structcrow_1_1json_1_1detail_1_1r__string.html#a3d4f439775bf61521c661a96b647ff0b", null ], + [ "r_string", "structcrow_1_1json_1_1detail_1_1r__string.html#a7b25d57ab7b1d9235ca113a67512af66", null ], + [ "begin", "structcrow_1_1json_1_1detail_1_1r__string.html#a429b7faf8cc466e4ceb3ff03a1dc3aa4", null ], + [ "end", "structcrow_1_1json_1_1detail_1_1r__string.html#a79796d096fa414ec85b985ee7882a03a", null ], + [ "operator std::string", "structcrow_1_1json_1_1detail_1_1r__string.html#a03ebb96ab3089fcd67869d503fad66fc", null ], + [ "operator=", "structcrow_1_1json_1_1detail_1_1r__string.html#a50a109ca9049b26afd6a6e5affc73fff", null ], + [ "operator=", "structcrow_1_1json_1_1detail_1_1r__string.html#ae67f6ae5f2705cd1dd391bb939f53bc8", null ], + [ "size", "structcrow_1_1json_1_1detail_1_1r__string.html#ac249212e937db5b1f036270350a114e2", null ], + [ "crow::json::load", "structcrow_1_1json_1_1detail_1_1r__string.html#aafce907806967e65bf422f4907f26813", null ], + [ "operator<<", "structcrow_1_1json_1_1detail_1_1r__string.html#a4d4e7c489d50d83afcf5a8ce9264e4bb", null ], + [ "operator==", "structcrow_1_1json_1_1detail_1_1r__string.html#aab3b53514a32f8e276f2959fb5bfb6a3", null ], + [ "operator==", "structcrow_1_1json_1_1detail_1_1r__string.html#af5b7e5e5196e2b0fd83277dc0f21b2ba", null ], + [ "operator==", "structcrow_1_1json_1_1detail_1_1r__string.html#a52f128692ac8eab6e11ca0b80d923e72", null ], + [ "e_", "structcrow_1_1json_1_1detail_1_1r__string.html#adeb368c4c0dfeb349bb32129e8dee23b", null ], + [ "owned_", "structcrow_1_1json_1_1detail_1_1r__string.html#aebfcc625db6a89f8c358292165a2fdd2", null ], + [ "s_", "structcrow_1_1json_1_1detail_1_1r__string.html#a9a0a048fb2cb904e8336926817947448", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1json_1_1wvalue__reader-members.html b/1.2/reference/structcrow_1_1json_1_1wvalue__reader-members.html new file mode 100644 index 000000000..868afca71 --- /dev/null +++ b/1.2/reference/structcrow_1_1json_1_1wvalue__reader-members.html @@ -0,0 +1,124 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::json::wvalue_reader Member List
+
+
+ +

This is the complete list of members for crow::json::wvalue_reader, including all inherited members.

+ + + + + + +
get(int64_t fallback) (defined in crow::json::wvalue_reader)crow::json::wvalue_readerinline
get(double fallback) (defined in crow::json::wvalue_reader)crow::json::wvalue_readerinline
get(bool fallback) (defined in crow::json::wvalue_reader)crow::json::wvalue_readerinline
get(const std::string &fallback) (defined in crow::json::wvalue_reader)crow::json::wvalue_readerinline
ref (defined in crow::json::wvalue_reader)crow::json::wvalue_reader
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1json_1_1wvalue__reader.html b/1.2/reference/structcrow_1_1json_1_1wvalue__reader.html new file mode 100644 index 000000000..7a298cf8c --- /dev/null +++ b/1.2/reference/structcrow_1_1json_1_1wvalue__reader.html @@ -0,0 +1,146 @@ + + + + + + + + Crow: crow::json::wvalue_reader Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::json::wvalue_reader Struct Reference
+
+
+ + + + + + + + + + +

+Public Member Functions

+int64_t get (int64_t fallback)
 
+double get (double fallback)
 
+bool get (bool fallback)
 
+std::string get (const std::string &fallback)
 
+ + + +

+Public Attributes

+const wvalueref
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1json_1_1wvalue__reader.js b/1.2/reference/structcrow_1_1json_1_1wvalue__reader.js new file mode 100644 index 000000000..550efbb20 --- /dev/null +++ b/1.2/reference/structcrow_1_1json_1_1wvalue__reader.js @@ -0,0 +1,8 @@ +var structcrow_1_1json_1_1wvalue__reader = +[ + [ "get", "structcrow_1_1json_1_1wvalue__reader.html#a90df23f22a3f808e264cf77da2089fa5", null ], + [ "get", "structcrow_1_1json_1_1wvalue__reader.html#a8d24fd728fe16e5f50b1fdda27c2bcd7", null ], + [ "get", "structcrow_1_1json_1_1wvalue__reader.html#abeca5ac7cbdbfccc2d611822c653a49d", null ], + [ "get", "structcrow_1_1json_1_1wvalue__reader.html#a1f7615cec0f62f45ab30734a738b4f95", null ], + [ "ref", "structcrow_1_1json_1_1wvalue__reader.html#aef19e43413c6d1265aba800b6aafed17", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1multipart_1_1header-members.html b/1.2/reference/structcrow_1_1multipart_1_1header-members.html new file mode 100644 index 000000000..b49300b75 --- /dev/null +++ b/1.2/reference/structcrow_1_1multipart_1_1header-members.html @@ -0,0 +1,123 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::multipart::header Member List
+
+
+ +

This is the complete list of members for crow::multipart::header, including all inherited members.

+ + + + + +
operator double() constcrow::multipart::headerinline
operator int() constcrow::multipart::headerinline
paramscrow::multipart::header
valuecrow::multipart::header
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1multipart_1_1header.html b/1.2/reference/structcrow_1_1multipart_1_1header.html new file mode 100644 index 000000000..29cfb9c1d --- /dev/null +++ b/1.2/reference/structcrow_1_1multipart_1_1header.html @@ -0,0 +1,154 @@ + + + + + + + + Crow: crow::multipart::header Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::multipart::header Struct Reference
+
+
+ +

The first part in a section, contains metadata about the part. + More...

+ +

#include <multipart.h>

+ + + + + + + + +

+Public Member Functions

operator int () const
 Returns value as integer.
 
operator double () const
 Returns value as double.
 
+ + + + + + + +

+Public Attributes

+std::string value
 The first part of the header, usually Content-Type or Content-Disposition
 
+std::unordered_map< std::string, std::string > params
 The parameters of the header, come after the value
 
+

Detailed Description

+

The first part in a section, contains metadata about the part.

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1multipart_1_1header.js b/1.2/reference/structcrow_1_1multipart_1_1header.js new file mode 100644 index 000000000..907a99683 --- /dev/null +++ b/1.2/reference/structcrow_1_1multipart_1_1header.js @@ -0,0 +1,7 @@ +var structcrow_1_1multipart_1_1header = +[ + [ "operator double", "structcrow_1_1multipart_1_1header.html#a0b87278e0ebe8d323f46c9ed64fc385a", null ], + [ "operator int", "structcrow_1_1multipart_1_1header.html#adff380493f414108eb67420d06d426ee", null ], + [ "params", "structcrow_1_1multipart_1_1header.html#a18422d09aac9c5d5751799862d41a73c", null ], + [ "value", "structcrow_1_1multipart_1_1header.html#aec60ea97914c4b9b102c3d5c1e89330a", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1multipart_1_1message-members.html b/1.2/reference/structcrow_1_1multipart_1_1message-members.html new file mode 100644 index 000000000..cfdd9a865 --- /dev/null +++ b/1.2/reference/structcrow_1_1multipart_1_1message-members.html @@ -0,0 +1,132 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::multipart::message Member List
+
+
+ +

This is the complete list of members for crow::multipart::message, including all inherited members.

+ + + + + + + + + + + + + + +
boundarycrow::multipart::message
content_type (defined in crow::returnable)crow::returnable
dump() const overridecrow::multipart::messageinlinevirtual
dump(int part_) constcrow::multipart::messageinline
get_header_value(const std::string &key) const (defined in crow::multipart::message)crow::multipart::messageinline
get_part_by_name(const std::string &name) (defined in crow::multipart::message)crow::multipart::messageinline
headerscrow::multipart::message
message(const ci_map &headers, const std::string &boundary, const std::vector< part > &sections)crow::multipart::messageinline
message(const request &req)crow::multipart::messageinline
part_mapcrow::multipart::message
partscrow::multipart::message
returnable(std::string ctype) (defined in crow::returnable)crow::returnableinline
~returnable() (defined in crow::returnable)crow::returnableinlinevirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1multipart_1_1message.html b/1.2/reference/structcrow_1_1multipart_1_1message.html new file mode 100644 index 000000000..333806fbc --- /dev/null +++ b/1.2/reference/structcrow_1_1multipart_1_1message.html @@ -0,0 +1,193 @@ + + + + + + + + Crow: crow::multipart::message Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::multipart::message Struct Reference
+
+
+ +

The parsed multipart request/response. + More...

+ +

#include <multipart.h>

+
+Inheritance diagram for crow::multipart::message:
+
+
+ + +crow::returnable + +
+ + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

+const std::string & get_header_value (const std::string &key) const
 
+part get_part_by_name (const std::string &name)
 
+std::string dump () const override
 Represent all parts as a string (does not include message headers)
 
+std::string dump (int part_) const
 Represent an individual part as a string.
 
message (const ci_map &headers, const std::string &boundary, const std::vector< part > &sections)
 Default constructor using default values.
 
message (const request &req)
 Create a multipart message from a request data.
 
- Public Member Functions inherited from crow::returnable
returnable (std::string ctype)
 
+ + + + + + + + + + + + + + + + +

+Public Attributes

+ci_map headers
 The request/response headers.
 
+std::string boundary
 The text boundary that separates different parts
 
+std::vector< partparts
 The individual parts of the message.
 
+mp_map part_map
 The individual parts of the message, organized in a map with the name header parameter being the key.
 
- Public Attributes inherited from crow::returnable
+std::string content_type
 
+

Detailed Description

+

The parsed multipart request/response.

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1multipart_1_1message.js b/1.2/reference/structcrow_1_1multipart_1_1message.js new file mode 100644 index 000000000..538ea81d3 --- /dev/null +++ b/1.2/reference/structcrow_1_1multipart_1_1message.js @@ -0,0 +1,13 @@ +var structcrow_1_1multipart_1_1message = +[ + [ "message", "structcrow_1_1multipart_1_1message.html#a0007fa0cadffae1a8d16fac169d1527b", null ], + [ "message", "structcrow_1_1multipart_1_1message.html#a32946a0f39a8d024aaf4643116a7561b", null ], + [ "dump", "structcrow_1_1multipart_1_1message.html#adac4c7af1a5d0eb66c2accbaf80e0196", null ], + [ "dump", "structcrow_1_1multipart_1_1message.html#abeeebf36687f9cbdf06a6521eac1ce33", null ], + [ "get_header_value", "structcrow_1_1multipart_1_1message.html#a6096bf07a476710b1d4bd5855bf96be3", null ], + [ "get_part_by_name", "structcrow_1_1multipart_1_1message.html#a4c3a0575f52bd6e91e539b6aa168d5fd", null ], + [ "boundary", "structcrow_1_1multipart_1_1message.html#a56eb4bbf64d4930663ac4d5dd7b77d34", null ], + [ "headers", "structcrow_1_1multipart_1_1message.html#ae333adda5d66d21018a978e6a3c317dd", null ], + [ "part_map", "structcrow_1_1multipart_1_1message.html#a76d89e2bff4c90307053bcb895d334ec", null ], + [ "parts", "structcrow_1_1multipart_1_1message.html#a05e9cf3feb60f4534af334b2dd5eadf2", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1multipart_1_1message.png b/1.2/reference/structcrow_1_1multipart_1_1message.png new file mode 100644 index 000000000..1d7cb5932 Binary files /dev/null and b/1.2/reference/structcrow_1_1multipart_1_1message.png differ diff --git a/1.2/reference/structcrow_1_1multipart_1_1part-members.html b/1.2/reference/structcrow_1_1multipart_1_1part-members.html new file mode 100644 index 000000000..0e3eb2ebf --- /dev/null +++ b/1.2/reference/structcrow_1_1multipart_1_1part-members.html @@ -0,0 +1,124 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::multipart::part Member List
+
+
+ +

This is the complete list of members for crow::multipart::part, including all inherited members.

+ + + + + + +
bodycrow::multipart::part
get_header_object(const std::string &key) const (defined in crow::multipart::part)crow::multipart::partinline
headerscrow::multipart::part
operator double() constcrow::multipart::partinline
operator int() constcrow::multipart::partinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1multipart_1_1part.html b/1.2/reference/structcrow_1_1multipart_1_1part.html new file mode 100644 index 000000000..11e538ea3 --- /dev/null +++ b/1.2/reference/structcrow_1_1multipart_1_1part.html @@ -0,0 +1,158 @@ + + + + + + + + Crow: crow::multipart::part Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::multipart::part Struct Reference
+
+
+ +

One part of the multipart message. + More...

+ +

#include <multipart.h>

+ + + + + + + + + + +

+Public Member Functions

operator int () const
 Returns body as integer.
 
operator double () const
 Returns body as double.
 
+const headerget_header_object (const std::string &key) const
 
+ + + + + + + +

+Public Attributes

+mph_map headers
 (optional) The first part before the data, Contains information regarding the type of data and encoding
 
+std::string body
 The actual data in the part.
 
+

Detailed Description

+

One part of the multipart message.

+

It is usually separated from other sections by a boundary

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1multipart_1_1part.js b/1.2/reference/structcrow_1_1multipart_1_1part.js new file mode 100644 index 000000000..bde5a7696 --- /dev/null +++ b/1.2/reference/structcrow_1_1multipart_1_1part.js @@ -0,0 +1,8 @@ +var structcrow_1_1multipart_1_1part = +[ + [ "get_header_object", "structcrow_1_1multipart_1_1part.html#a26b945bead6cd9fc914cd9d9ad086553", null ], + [ "operator double", "structcrow_1_1multipart_1_1part.html#ac9c4ebeeabe158725bc67cf14c9f957e", null ], + [ "operator int", "structcrow_1_1multipart_1_1part.html#a06851f0fd2d36b71139e8488fb646b7e", null ], + [ "body", "structcrow_1_1multipart_1_1part.html#acbfa0a181e86a89dccdf70d985365695", null ], + [ "headers", "structcrow_1_1multipart_1_1part.html#a8ff7f3aac814d93500d475da150fcbc6", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1mustache_1_1_action-members.html b/1.2/reference/structcrow_1_1mustache_1_1_action-members.html new file mode 100644 index 000000000..6465ba1ba --- /dev/null +++ b/1.2/reference/structcrow_1_1mustache_1_1_action-members.html @@ -0,0 +1,124 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::mustache::Action Member List
+
+
+ +

This is the complete list of members for crow::mustache::Action, including all inherited members.

+ + + + + + +
Action(ActionType t, size_t start, size_t end, size_t pos=0) (defined in crow::mustache::Action)crow::mustache::Actioninline
end (defined in crow::mustache::Action)crow::mustache::Action
pos (defined in crow::mustache::Action)crow::mustache::Action
start (defined in crow::mustache::Action)crow::mustache::Action
t (defined in crow::mustache::Action)crow::mustache::Action
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1mustache_1_1_action.html b/1.2/reference/structcrow_1_1mustache_1_1_action.html new file mode 100644 index 000000000..442047080 --- /dev/null +++ b/1.2/reference/structcrow_1_1mustache_1_1_action.html @@ -0,0 +1,146 @@ + + + + + + + + Crow: crow::mustache::Action Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::mustache::Action Struct Reference
+
+
+ + + + +

+Public Member Functions

Action (ActionType t, size_t start, size_t end, size_t pos=0)
 
+ + + + + + + + + +

+Public Attributes

+int start
 
+int end
 
+int pos
 
+ActionType t
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1mustache_1_1_action.js b/1.2/reference/structcrow_1_1mustache_1_1_action.js new file mode 100644 index 000000000..8d9a210f4 --- /dev/null +++ b/1.2/reference/structcrow_1_1mustache_1_1_action.js @@ -0,0 +1,8 @@ +var structcrow_1_1mustache_1_1_action = +[ + [ "Action", "structcrow_1_1mustache_1_1_action.html#abdd01c3d42e0b9943cc07cc511cb972c", null ], + [ "end", "structcrow_1_1mustache_1_1_action.html#ac0daea6290bb2ca9c9c87c3fb163ce7d", null ], + [ "pos", "structcrow_1_1mustache_1_1_action.html#a1af3f38c04cdc0978c2a788eeda81eab", null ], + [ "start", "structcrow_1_1mustache_1_1_action.html#a643c89b2d81bfc2d2eedfca0cb119068", null ], + [ "t", "structcrow_1_1mustache_1_1_action.html#aed7c3e6311655c446b56c31210e27ff4", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1mustache_1_1rendered__template-members.html b/1.2/reference/structcrow_1_1mustache_1_1rendered__template-members.html new file mode 100644 index 000000000..64e8da9ed --- /dev/null +++ b/1.2/reference/structcrow_1_1mustache_1_1rendered__template-members.html @@ -0,0 +1,126 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::mustache::rendered_template Member List
+
+
+ +

This is the complete list of members for crow::mustache::rendered_template, including all inherited members.

+ + + + + + + + +
body_ (defined in crow::mustache::rendered_template)crow::mustache::rendered_template
content_type (defined in crow::returnable)crow::returnable
dump() const override (defined in crow::mustache::rendered_template)crow::mustache::rendered_templateinlinevirtual
rendered_template() (defined in crow::mustache::rendered_template)crow::mustache::rendered_templateinline
rendered_template(std::string &body) (defined in crow::mustache::rendered_template)crow::mustache::rendered_templateinline
returnable(std::string ctype) (defined in crow::returnable)crow::returnableinline
~returnable() (defined in crow::returnable)crow::returnableinlinevirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1mustache_1_1rendered__template.html b/1.2/reference/structcrow_1_1mustache_1_1rendered__template.html new file mode 100644 index 000000000..82244430f --- /dev/null +++ b/1.2/reference/structcrow_1_1mustache_1_1rendered__template.html @@ -0,0 +1,157 @@ + + + + + + + + Crow: crow::mustache::rendered_template Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::mustache::rendered_template Struct Reference
+
+
+
+Inheritance diagram for crow::mustache::rendered_template:
+
+
+ + +crow::returnable + +
+ + + + + + + + + +

+Public Member Functions

rendered_template (std::string &body)
 
+std::string dump () const override
 
- Public Member Functions inherited from crow::returnable
returnable (std::string ctype)
 
+ + + + + + +

+Public Attributes

+std::string body_
 
- Public Attributes inherited from crow::returnable
+std::string content_type
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1mustache_1_1rendered__template.js b/1.2/reference/structcrow_1_1mustache_1_1rendered__template.js new file mode 100644 index 000000000..d855aeebb --- /dev/null +++ b/1.2/reference/structcrow_1_1mustache_1_1rendered__template.js @@ -0,0 +1,7 @@ +var structcrow_1_1mustache_1_1rendered__template = +[ + [ "rendered_template", "structcrow_1_1mustache_1_1rendered__template.html#abc95a00b4666fa9d2f563025fe4a2bc0", null ], + [ "rendered_template", "structcrow_1_1mustache_1_1rendered__template.html#aca7c4ee2611c3926861807cd81436e8e", null ], + [ "dump", "structcrow_1_1mustache_1_1rendered__template.html#a4b13f956d00628f86e4a5e4abe0a9ea0", null ], + [ "body_", "structcrow_1_1mustache_1_1rendered__template.html#a1659ce2123d211a44e991a93e80ad0b4", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1mustache_1_1rendered__template.png b/1.2/reference/structcrow_1_1mustache_1_1rendered__template.png new file mode 100644 index 000000000..41342eb2a Binary files /dev/null and b/1.2/reference/structcrow_1_1mustache_1_1rendered__template.png differ diff --git a/1.2/reference/structcrow_1_1request-members.html b/1.2/reference/structcrow_1_1request-members.html new file mode 100644 index 000000000..1bb3a0515 --- /dev/null +++ b/1.2/reference/structcrow_1_1request-members.html @@ -0,0 +1,142 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::request Member List
+
+
+ +

This is the complete list of members for crow::request, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + +
add_header(std::string key, std::string value) (defined in crow::request)crow::requestinline
body (defined in crow::request)crow::request
check_version(unsigned char major, unsigned char minor) const (defined in crow::request)crow::requestinline
close_connectioncrow::request
dispatch(CompletionHandler handler)crow::requestinline
get_body_params() constcrow::requestinline
get_header_value(const std::string &key) const (defined in crow::request)crow::requestinline
headers (defined in crow::request)crow::request
http_ver_major (defined in crow::request)crow::request
http_ver_minor (defined in crow::request)crow::request
io_service (defined in crow::request)crow::request
keep_alivecrow::request
method (defined in crow::request)crow::request
middleware_container (defined in crow::request)crow::request
middleware_context (defined in crow::request)crow::request
post(CompletionHandler handler)crow::requestinline
raw_urlcrow::request
remote_ip_addresscrow::request
request()crow::requestinline
request(HTTPMethod method, std::string raw_url, std::string url, query_string url_params, ci_map headers, std::string body, unsigned char http_major, unsigned char http_minor, bool has_keep_alive, bool has_close_connection, bool is_upgrade)crow::requestinline
upgradecrow::request
urlcrow::request
url_paramscrow::request
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1request.html b/1.2/reference/structcrow_1_1request.html new file mode 100644 index 000000000..6311a176f --- /dev/null +++ b/1.2/reference/structcrow_1_1request.html @@ -0,0 +1,249 @@ + + + + + + + + Crow: crow::request Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::request Struct Reference
+
+
+ +

An HTTP request. + More...

+ +

#include <http_request.h>

+ + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

request ()
 Construct an empty request. (sets the method to GET)
 
request (HTTPMethod method, std::string raw_url, std::string url, query_string url_params, ci_map headers, std::string body, unsigned char http_major, unsigned char http_minor, bool has_keep_alive, bool has_close_connection, bool is_upgrade)
 Construct a request with all values assigned.
 
+void add_header (std::string key, std::string value)
 
+const std::string & get_header_value (const std::string &key) const
 
+bool check_version (unsigned char major, unsigned char minor) const
 
const query_string get_body_params () const
 Get the body as parameters in QS format. More...
 
+template<typename CompletionHandler >
void post (CompletionHandler handler)
 Send data to whoever made this request with a completion handler and return immediately.
 
+template<typename CompletionHandler >
void dispatch (CompletionHandler handler)
 Send data to whoever made this request with a completion handler.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Attributes

+HTTPMethod method
 
+std::string raw_url
 The full URL containing the ? and URL parameters.
 
+std::string url
 The endpoint without any parameters.
 
+query_string url_params
 The parameters associated with the request. (everything after the ? in the URL)
 
+ci_map headers
 
+std::string body
 
+std::string remote_ip_address
 The IP address from which the request was sent.
 
+unsigned char http_ver_major
 
+unsigned char http_ver_minor
 
+bool keep_alive
 Whether or not the server should send a connection: Keep-Alive header to the client.
 
+bool close_connection
 Whether or not the server should shut down the TCP connection once a response is sent.
 
+bool upgrade
 Whether or noth the server should change the HTTP connection to a different connection.
 
+void * middleware_context {}
 
+void * middleware_container {}
 
+asio::io_service * io_service {}
 
+

Detailed Description

+

An HTTP request.

+

Member Function Documentation

+ +

◆ get_body_params()

+ +
+
+ + + + + +
+ + + + + + + +
const query_string crow::request::get_body_params () const
+
+inline
+
+ +

Get the body as parameters in QS format.

+

This is meant to be used with requests of type "application/x-www-form-urlencoded"

+ +
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1request.js b/1.2/reference/structcrow_1_1request.js new file mode 100644 index 000000000..243ae8363 --- /dev/null +++ b/1.2/reference/structcrow_1_1request.js @@ -0,0 +1,26 @@ +var structcrow_1_1request = +[ + [ "request", "structcrow_1_1request.html#a838c9a8c9a5eb2283d57e66f3630b5a6", null ], + [ "request", "structcrow_1_1request.html#a111b70ddb2a100a79415b539e152e145", null ], + [ "add_header", "structcrow_1_1request.html#a98b85749921fc63e57d6ea891fe17391", null ], + [ "check_version", "structcrow_1_1request.html#ac369309c6be61c011b93a5b8cf14515a", null ], + [ "dispatch", "structcrow_1_1request.html#ac3e72e3fe415c68618dee999e3984160", null ], + [ "get_body_params", "structcrow_1_1request.html#af2679155b496b7d8d80a82c0d9a175b5", null ], + [ "get_header_value", "structcrow_1_1request.html#a81e389dddb3f59bdb667097371573356", null ], + [ "post", "structcrow_1_1request.html#a33aa146a3914864ce82ef22136451601", null ], + [ "body", "structcrow_1_1request.html#afff683ed63a9e4067683786c3c6218c2", null ], + [ "close_connection", "structcrow_1_1request.html#a4a3e4bcd0cd626ceaee38f4c17d28c8d", null ], + [ "headers", "structcrow_1_1request.html#a86d6c2a93b50611c4a5b5643b6da6540", null ], + [ "http_ver_major", "structcrow_1_1request.html#aa51aa45a03c2efe581e9bf9f011e8378", null ], + [ "http_ver_minor", "structcrow_1_1request.html#ac0603f5ffe5c7b93c0ca3a5bed4ebacc", null ], + [ "io_service", "structcrow_1_1request.html#a3752ac015c6ba0047842a4594e4e9ad5", null ], + [ "keep_alive", "structcrow_1_1request.html#a5148ce95969d261e50ee977c1dc7960c", null ], + [ "method", "structcrow_1_1request.html#a79ac893dd6ad4ec5752dea0cec65ce71", null ], + [ "middleware_container", "structcrow_1_1request.html#a7b0dbe01000f103306f1b8370e0394b4", null ], + [ "middleware_context", "structcrow_1_1request.html#a9de0c8721b1c26aab317db0bcdcf1b8a", null ], + [ "raw_url", "structcrow_1_1request.html#a72f5504a56f9ba70d7d33f86aaf9bc8a", null ], + [ "remote_ip_address", "structcrow_1_1request.html#aa8a04e30e2249f04614f233d25ffaad7", null ], + [ "upgrade", "structcrow_1_1request.html#ac4b5e2e32e2e0b633211925158b03559", null ], + [ "url", "structcrow_1_1request.html#aa3df34c56847d6d42887e73655276167", null ], + [ "url_params", "structcrow_1_1request.html#a745d5a94e9e9ae1fed64674aae0194b0", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1response-members.html b/1.2/reference/structcrow_1_1response-members.html new file mode 100644 index 000000000..a0d1eb771 --- /dev/null +++ b/1.2/reference/structcrow_1_1response-members.html @@ -0,0 +1,158 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::response Member List
+
+
+ +

This is the complete list of members for crow::response, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
add_header(std::string key, std::string value)crow::responseinline
bodycrow::response
clear() (defined in crow::response)crow::responseinline
codecrow::response
compressedcrow::response
crow::Connection (defined in crow::response)crow::responsefriend
end()crow::responseinline
end(const std::string &body_part)crow::responseinline
get_header_value(const std::string &key) (defined in crow::response)crow::responseinline
get_mime_type(const std::string &contentType) (defined in crow::response)crow::responseinlinestatic
headerscrow::response
is_alive()crow::responseinline
is_completed() const noexceptcrow::responseinline
is_static_type()crow::responseinline
manual_length_headercrow::response
moved(const std::string &location)crow::responseinline
moved_perm(const std::string &location)crow::responseinline
operator=(const response &r)=delete (defined in crow::response)crow::response
operator=(response &&r) noexcept (defined in crow::response)crow::responseinline
redirect(const std::string &location)crow::responseinline
redirect_perm(const std::string &location)crow::responseinline
response() (defined in crow::response)crow::responseinline
response(int code) (defined in crow::response)crow::responseinlineexplicit
response(std::string body) (defined in crow::response)crow::responseinline
response(int code, std::string body) (defined in crow::response)crow::responseinline
response(returnable &&value) (defined in crow::response)crow::responseinline
response(returnable &value) (defined in crow::response)crow::responseinline
response(int code, returnable &value) (defined in crow::response)crow::responseinline
response(int code, returnable &&value) (defined in crow::response)crow::responseinline
response(response &&r) (defined in crow::response)crow::responseinline
response(std::string contentType, std::string body) (defined in crow::response)crow::responseinline
response(int code, std::string contentType, std::string body) (defined in crow::response)crow::responseinline
Router (defined in crow::response)crow::responsefriend
set_header(std::string key, std::string value)crow::responseinline
set_static_file_info(std::string path)crow::responseinline
set_static_file_info_unsafe(std::string path)crow::responseinline
skip_bodycrow::response
validate_mime_type(const std::string &candidate) noexcept (defined in crow::response)crow::responseinlinestatic
write(const std::string &body_part) (defined in crow::response)crow::responseinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1response.html b/1.2/reference/structcrow_1_1response.html new file mode 100644 index 000000000..e1a221ff6 --- /dev/null +++ b/1.2/reference/structcrow_1_1response.html @@ -0,0 +1,400 @@ + + + + + + + + Crow: crow::response Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ + +
+ +

HTTP response. + More...

+ +

#include <http_response.h>

+ + + + + +

+Classes

struct  static_file_info
 This constains metadata (coming from the stat command) related to any static files associated with this response. More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

+void set_header (std::string key, std::string value)
 Set the value of an existing header in the response.
 
+void add_header (std::string key, std::string value)
 Add a new header to the response.
 
+const std::string & get_header_value (const std::string &key)
 
response (int code)
 
response (std::string body)
 
response (int code, std::string body)
 
response (returnable &&value)
 
response (returnable &value)
 
response (int code, returnable &value)
 
response (int code, returnable &&value)
 
response (response &&r)
 
response (std::string contentType, std::string body)
 
response (int code, std::string contentType, std::string body)
 
+responseoperator= (const response &r)=delete
 
+responseoperator= (response &&r) noexcept
 
+bool is_completed () const noexcept
 Check if the response has completed (whether response.end() has been called)
 
+void clear ()
 
void redirect (const std::string &location)
 Return a "Temporary Redirect" response. More...
 
void redirect_perm (const std::string &location)
 Return a "Permanent Redirect" response. More...
 
void moved (const std::string &location)
 Return a "Found (Moved Temporarily)" response. More...
 
void moved_perm (const std::string &location)
 Return a "Moved Permanently" response. More...
 
+void write (const std::string &body_part)
 
+void end ()
 Set the response completion flag and call the handler (to send the response).
 
+void end (const std::string &body_part)
 Same as end() except it adds a body part right before ending.
 
+bool is_alive ()
 Check if the connection is still alive (usually by checking the socket status).
 
+bool is_static_type ()
 Check whether the response has a static file defined.
 
+void set_static_file_info (std::string path)
 Return a static file as the response body.
 
+void set_static_file_info_unsafe (std::string path)
 Return a static file as the response body without sanitizing the path (use set_static_file_info instead)
 
+ + + + + +

+Static Public Member Functions

+static bool validate_mime_type (const std::string &candidate) noexcept
 
+static std::string get_mime_type (const std::string &contentType)
 
+ + + + + + + + + + + + + + + + + + + +

+Public Attributes

+int code {200}
 The Status code for the response.
 
+std::string body
 The actual payload containing the response data.
 
+ci_map headers
 HTTP headers.
 
+bool compressed = true
 If compression is enabled and this is false, the individual response will not be compressed.
 
+bool skip_body = false
 Whether this is a response to a HEAD request.
 
+bool manual_length_header = false
 Whether Crow should automatically add a "Content-Length" header.
 
+ + + + + + +

+Friends

+template<typename Adaptor , typename Handler , typename... Middlewares>
class crow::Connection
 
+class Router
 
+

Detailed Description

+

HTTP response.

+

Member Function Documentation

+ +

◆ moved()

+ +
+
+ + + + + +
+ + + + + + + + +
void crow::response::moved (const std::string & location)
+
+inline
+
+ +

Return a "Found (Moved Temporarily)" response.

+

Location can either be a route or a full URL.

+ +
+
+ +

◆ moved_perm()

+ +
+
+ + + + + +
+ + + + + + + + +
void crow::response::moved_perm (const std::string & location)
+
+inline
+
+ +

Return a "Moved Permanently" response.

+

Location can either be a route or a full URL.

+ +
+
+ +

◆ redirect()

+ +
+
+ + + + + +
+ + + + + + + + +
void crow::response::redirect (const std::string & location)
+
+inline
+
+ +

Return a "Temporary Redirect" response.

+

Location can either be a route or a full URL.

+ +
+
+ +

◆ redirect_perm()

+ +
+
+ + + + + +
+ + + + + + + + +
void crow::response::redirect_perm (const std::string & location)
+
+inline
+
+ +

Return a "Permanent Redirect" response.

+

Location can either be a route or a full URL.

+ +
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1response.js b/1.2/reference/structcrow_1_1response.js new file mode 100644 index 000000000..cf79e7300 --- /dev/null +++ b/1.2/reference/structcrow_1_1response.js @@ -0,0 +1,41 @@ +var structcrow_1_1response = +[ + [ "static_file_info", "structcrow_1_1response_1_1static__file__info.html", "structcrow_1_1response_1_1static__file__info" ], + [ "response", "structcrow_1_1response.html#a0f4955bc5dc914d698cff5e83bca1cdb", null ], + [ "response", "structcrow_1_1response.html#a52e2658b1d16dcf106ed138b6396696b", null ], + [ "response", "structcrow_1_1response.html#aab7485cb8f0efa3fcf062118476edfd5", null ], + [ "response", "structcrow_1_1response.html#aeee8e7dd021783524bae9bd8775bae0f", null ], + [ "response", "structcrow_1_1response.html#a693fd3f57d926251918b16a6f20be474", null ], + [ "response", "structcrow_1_1response.html#a70c56fc6910c94f42accb77a45d5686e", null ], + [ "response", "structcrow_1_1response.html#a37aaf5b69473066fe8bcf302e9ba4580", null ], + [ "response", "structcrow_1_1response.html#a3b9bfae36855265ddc1a64c78d0caf8e", null ], + [ "response", "structcrow_1_1response.html#abd924a9b90dfb505804fe4cf791768a3", null ], + [ "response", "structcrow_1_1response.html#ac7f3e75d48f2082a93e366d31298eb72", null ], + [ "response", "structcrow_1_1response.html#a58dd09e8a9b3f1d86fe9d676757c8a2c", null ], + [ "add_header", "structcrow_1_1response.html#a16d1a8bcec6460ba97f90b80881693b8", null ], + [ "clear", "structcrow_1_1response.html#a068269fc8b7f1df3d5421ccd384fe1f3", null ], + [ "end", "structcrow_1_1response.html#abef42200eca49c70dc1f5140ee3603ab", null ], + [ "end", "structcrow_1_1response.html#a10da2e17421586b68f27ef1533ec677b", null ], + [ "get_header_value", "structcrow_1_1response.html#a8c35e92bc75eaa35f45e0ca6d22a8f47", null ], + [ "is_alive", "structcrow_1_1response.html#ac29da52ee1e0b55086cd8eedd6c22da1", null ], + [ "is_completed", "structcrow_1_1response.html#a9fb82c40e0c0844db70b7b86b4a23e9f", null ], + [ "is_static_type", "structcrow_1_1response.html#aff527a091cf5054e933a244b078648c1", null ], + [ "moved", "structcrow_1_1response.html#a760bca5f5fdee03518d59d9538ce5432", null ], + [ "moved_perm", "structcrow_1_1response.html#a9ee58f8b775b2566418b298fe33c0dcc", null ], + [ "operator=", "structcrow_1_1response.html#ad0b5402527b2c0e985d9eaf97e0e4e2f", null ], + [ "operator=", "structcrow_1_1response.html#ae789c998922616a1a895476eb89c7844", null ], + [ "redirect", "structcrow_1_1response.html#ac04bbe2d4f54fd717cdffdb26af3e46f", null ], + [ "redirect_perm", "structcrow_1_1response.html#a9e87a17c3cf8b434fd2a64a9b3d4b675", null ], + [ "set_header", "structcrow_1_1response.html#ab2b9a9b9795fa6330bd47b66a716cb0b", null ], + [ "set_static_file_info", "structcrow_1_1response.html#a8f5e5caa08c3e658bccd03996e1a778a", null ], + [ "set_static_file_info_unsafe", "structcrow_1_1response.html#adaaa1a62451d41e6f3831463296b4c08", null ], + [ "write", "structcrow_1_1response.html#a82bba7eaacfee514c55630a13a85410e", null ], + [ "crow::Connection", "structcrow_1_1response.html#a13cd54cff7b7cea484654c3e9ace415d", null ], + [ "Router", "structcrow_1_1response.html#ad1fd3424328f664cd049fe429e0e3dc6", null ], + [ "body", "structcrow_1_1response.html#ae9f3cc153eac05954f1f4e599527892d", null ], + [ "code", "structcrow_1_1response.html#aabc1f9b3264b8c5a2d05dcb409e8ff3f", null ], + [ "compressed", "structcrow_1_1response.html#af87163fd1c7e18650c7691e07f58c7de", null ], + [ "headers", "structcrow_1_1response.html#ae56cfc39f24a56748c11016842427fb3", null ], + [ "manual_length_header", "structcrow_1_1response.html#a95f300c05782e1934dad522b6d6588cf", null ], + [ "skip_body", "structcrow_1_1response.html#a548c4f5e059a7bb3b2560b7ac5800011", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1response_1_1static__file__info-members.html b/1.2/reference/structcrow_1_1response_1_1static__file__info-members.html new file mode 100644 index 000000000..fa790b498 --- /dev/null +++ b/1.2/reference/structcrow_1_1response_1_1static__file__info-members.html @@ -0,0 +1,122 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::response::static_file_info Member List
+
+
+ +

This is the complete list of members for crow::response::static_file_info, including all inherited members.

+ + + + +
path (defined in crow::response::static_file_info)crow::response::static_file_info
statbuf (defined in crow::response::static_file_info)crow::response::static_file_info
statResult (defined in crow::response::static_file_info)crow::response::static_file_info
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1response_1_1static__file__info.html b/1.2/reference/structcrow_1_1response_1_1static__file__info.html new file mode 100644 index 000000000..40544f968 --- /dev/null +++ b/1.2/reference/structcrow_1_1response_1_1static__file__info.html @@ -0,0 +1,144 @@ + + + + + + + + Crow: crow::response::static_file_info Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::response::static_file_info Struct Reference
+
+
+ +

This constains metadata (coming from the stat command) related to any static files associated with this response. + More...

+ +

#include <http_response.h>

+ + + + + + + + +

+Public Attributes

+std::string path = ""
 
+struct stat statbuf
 
+int statResult
 
+

Detailed Description

+

This constains metadata (coming from the stat command) related to any static files associated with this response.

+

Either a static file or a string body can be returned as 1 response.

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1response_1_1static__file__info.js b/1.2/reference/structcrow_1_1response_1_1static__file__info.js new file mode 100644 index 000000000..7161b86bd --- /dev/null +++ b/1.2/reference/structcrow_1_1response_1_1static__file__info.js @@ -0,0 +1,6 @@ +var structcrow_1_1response_1_1static__file__info = +[ + [ "path", "structcrow_1_1response_1_1static__file__info.html#ad734ec67dfb67063686fee4248586d70", null ], + [ "statbuf", "structcrow_1_1response_1_1static__file__info.html#aa38a0eee147e34c7459a6a720c67c286", null ], + [ "statResult", "structcrow_1_1response_1_1static__file__info.html#acdf1156faff4794e312d4388317cb804", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1returnable-members.html b/1.2/reference/structcrow_1_1returnable-members.html new file mode 100644 index 000000000..3431ec772 --- /dev/null +++ b/1.2/reference/structcrow_1_1returnable-members.html @@ -0,0 +1,123 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::returnable Member List
+
+
+ +

This is the complete list of members for crow::returnable, including all inherited members.

+ + + + + +
content_type (defined in crow::returnable)crow::returnable
dump() const =0 (defined in crow::returnable)crow::returnablepure virtual
returnable(std::string ctype) (defined in crow::returnable)crow::returnableinline
~returnable() (defined in crow::returnable)crow::returnableinlinevirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1returnable.html b/1.2/reference/structcrow_1_1returnable.html new file mode 100644 index 000000000..e54287c59 --- /dev/null +++ b/1.2/reference/structcrow_1_1returnable.html @@ -0,0 +1,158 @@ + + + + + + + + Crow: crow::returnable Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::returnable Struct Referenceabstract
+
+
+ +

An abstract class that allows any other class to be returned by a handler. + More...

+ +

#include <returnable.h>

+
+Inheritance diagram for crow::returnable:
+
+
+ + +crow::json::wvalue +crow::multipart::message +crow::mustache::rendered_template + +
+ + + + + + +

+Public Member Functions

+virtual std::string dump () const =0
 
returnable (std::string ctype)
 
+ + + +

+Public Attributes

+std::string content_type
 
+

Detailed Description

+

An abstract class that allows any other class to be returned by a handler.

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1returnable.js b/1.2/reference/structcrow_1_1returnable.js new file mode 100644 index 000000000..2b94f3a42 --- /dev/null +++ b/1.2/reference/structcrow_1_1returnable.js @@ -0,0 +1,7 @@ +var structcrow_1_1returnable = +[ + [ "returnable", "structcrow_1_1returnable.html#a33a00f3824916ae43f3b644d376c9353", null ], + [ "~returnable", "structcrow_1_1returnable.html#a43f2849da39aa97d68dd3db14c28a7ba", null ], + [ "dump", "structcrow_1_1returnable.html#a70b33327792023baec9ade42921234a6", null ], + [ "content_type", "structcrow_1_1returnable.html#a6f2c817b02551d6fb002a91b5587ba34", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1returnable.png b/1.2/reference/structcrow_1_1returnable.png new file mode 100644 index 000000000..3a575ea11 Binary files /dev/null and b/1.2/reference/structcrow_1_1returnable.png differ diff --git a/1.2/reference/structcrow_1_1routing__handle__result-members.html b/1.2/reference/structcrow_1_1routing__handle__result-members.html new file mode 100644 index 000000000..cc85e1605 --- /dev/null +++ b/1.2/reference/structcrow_1_1routing__handle__result-members.html @@ -0,0 +1,126 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::routing_handle_result Member List
+
+
+ +

This is the complete list of members for crow::routing_handle_result, including all inherited members.

+ + + + + + + + +
blueprint_indices (defined in crow::routing_handle_result)crow::routing_handle_result
method (defined in crow::routing_handle_result)crow::routing_handle_result
r_params (defined in crow::routing_handle_result)crow::routing_handle_result
routing_handle_result() (defined in crow::routing_handle_result)crow::routing_handle_resultinline
routing_handle_result(uint16_t rule_index_, std::vector< uint16_t > blueprint_indices_, routing_params r_params_) (defined in crow::routing_handle_result)crow::routing_handle_resultinline
routing_handle_result(uint16_t rule_index_, std::vector< uint16_t > blueprint_indices_, routing_params r_params_, HTTPMethod method_) (defined in crow::routing_handle_result)crow::routing_handle_resultinline
rule_index (defined in crow::routing_handle_result)crow::routing_handle_result
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1routing__handle__result.html b/1.2/reference/structcrow_1_1routing__handle__result.html new file mode 100644 index 000000000..a9503e299 --- /dev/null +++ b/1.2/reference/structcrow_1_1routing__handle__result.html @@ -0,0 +1,149 @@ + + + + + + + + Crow: crow::routing_handle_result Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::routing_handle_result Struct Reference
+
+
+ + + + + + +

+Public Member Functions

routing_handle_result (uint16_t rule_index_, std::vector< uint16_t > blueprint_indices_, routing_params r_params_)
 
routing_handle_result (uint16_t rule_index_, std::vector< uint16_t > blueprint_indices_, routing_params r_params_, HTTPMethod method_)
 
+ + + + + + + + + +

+Public Attributes

+uint16_t rule_index
 
+std::vector< uint16_t > blueprint_indices
 
+routing_params r_params
 
+HTTPMethod method
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1routing__handle__result.js b/1.2/reference/structcrow_1_1routing__handle__result.js new file mode 100644 index 000000000..12ab8854c --- /dev/null +++ b/1.2/reference/structcrow_1_1routing__handle__result.js @@ -0,0 +1,10 @@ +var structcrow_1_1routing__handle__result = +[ + [ "routing_handle_result", "structcrow_1_1routing__handle__result.html#a47c30a74abe870b2b23678c1f390d344", null ], + [ "routing_handle_result", "structcrow_1_1routing__handle__result.html#a0d91fe01b09f3f7648069e1dcceff4d1", null ], + [ "routing_handle_result", "structcrow_1_1routing__handle__result.html#aa0eb5e5466006a627bb02d84382f7cf6", null ], + [ "blueprint_indices", "structcrow_1_1routing__handle__result.html#a88df90b26edc1976dfd32c76f3552b52", null ], + [ "method", "structcrow_1_1routing__handle__result.html#a3b3b06d916e339c89dd3fee3840a438e", null ], + [ "r_params", "structcrow_1_1routing__handle__result.html#a8293d903ad88506f5f4386b5e20c4c7d", null ], + [ "rule_index", "structcrow_1_1routing__handle__result.html#aefe27184ee08b616c2700854345b6cda", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1session_1_1_cached_session-members.html b/1.2/reference/structcrow_1_1session_1_1_cached_session-members.html new file mode 100644 index 000000000..0bec5d962 --- /dev/null +++ b/1.2/reference/structcrow_1_1session_1_1_cached_session-members.html @@ -0,0 +1,127 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::session::CachedSession Member List
+
+ +
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1session_1_1_cached_session.html b/1.2/reference/structcrow_1_1session_1_1_cached_session.html new file mode 100644 index 000000000..0491ee3bc --- /dev/null +++ b/1.2/reference/structcrow_1_1session_1_1_cached_session.html @@ -0,0 +1,158 @@ + + + + + + + + Crow: crow::session::CachedSession Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::session::CachedSession Struct Reference
+
+
+ +

CachedSessions are shared across requests. + More...

+ +

#include <session.h>

+ + + + + + + + + + + + + + + + + + +

+Public Attributes

+std::string session_id
 
+std::string requested_session_id
 
+std::unordered_map< std::string, multi_valueentries
 
+std::unordered_set< std::string > dirty
 
+void * store_data
 
+bool requested_refresh
 
+int referrers
 
+std::recursive_mutex mutex
 
+

Detailed Description

+

CachedSessions are shared across requests.

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1session_1_1_cached_session.js b/1.2/reference/structcrow_1_1session_1_1_cached_session.js new file mode 100644 index 000000000..db5efacf6 --- /dev/null +++ b/1.2/reference/structcrow_1_1session_1_1_cached_session.js @@ -0,0 +1,11 @@ +var structcrow_1_1session_1_1_cached_session = +[ + [ "dirty", "structcrow_1_1session_1_1_cached_session.html#ab57226d045cff30e0e677f17cf6834c0", null ], + [ "entries", "structcrow_1_1session_1_1_cached_session.html#a557688ba5816d3d2b22c451fe4825625", null ], + [ "mutex", "structcrow_1_1session_1_1_cached_session.html#aad8990d246ebeaaf7053d476d7b0f330", null ], + [ "referrers", "structcrow_1_1session_1_1_cached_session.html#abb405f32f447fea38b0b37f077a044e1", null ], + [ "requested_refresh", "structcrow_1_1session_1_1_cached_session.html#ad32c4b8cb38d3003bdc9872b5abf6315", null ], + [ "requested_session_id", "structcrow_1_1session_1_1_cached_session.html#afcc184a4401405ad4da9e2df9cafd280", null ], + [ "session_id", "structcrow_1_1session_1_1_cached_session.html#acbbea79608b8cce857da26decd01c743", null ], + [ "store_data", "structcrow_1_1session_1_1_cached_session.html#af979ecc0cfa749da654e5a70e1c63793", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1session_1_1_expiration_tracker-members.html b/1.2/reference/structcrow_1_1session_1_1_expiration_tracker-members.html new file mode 100644 index 000000000..da891a538 --- /dev/null +++ b/1.2/reference/structcrow_1_1session_1_1_expiration_tracker-members.html @@ -0,0 +1,127 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::session::ExpirationTracker Member List
+
+
+ +

This is the complete list of members for crow::session::ExpirationTracker, including all inherited members.

+ + + + + + + + + +
add(std::string key, uint64_t time)crow::session::ExpirationTrackerinline
begin() const (defined in crow::session::ExpirationTracker)crow::session::ExpirationTrackerinline
DataPair typedef (defined in crow::session::ExpirationTracker)crow::session::ExpirationTracker
end() const (defined in crow::session::ExpirationTracker)crow::session::ExpirationTrackerinline
iterator typedef (defined in crow::session::ExpirationTracker)crow::session::ExpirationTracker
peek_first() constcrow::session::ExpirationTrackerinline
pop_first() (defined in crow::session::ExpirationTracker)crow::session::ExpirationTrackerinline
remove(const std::string &key) (defined in crow::session::ExpirationTracker)crow::session::ExpirationTrackerinline
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1session_1_1_expiration_tracker.html b/1.2/reference/structcrow_1_1session_1_1_expiration_tracker.html new file mode 100644 index 000000000..ec171ae6f --- /dev/null +++ b/1.2/reference/structcrow_1_1session_1_1_expiration_tracker.html @@ -0,0 +1,200 @@ + + + + + + + + Crow: crow::session::ExpirationTracker Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::session::ExpirationTracker Struct Reference
+
+
+ +

Expiration tracker keeps track of soonest-to-expire keys. + More...

+ +

#include <session.h>

+ + + + + + +

+Public Types

+using DataPair = std::pair< uint64_t, std::string >
 
+using iterator = typename std::set< DataPair >::const_iterator
 
+ + + + + + + + + + + + + + +

+Public Member Functions

void add (std::string key, uint64_t time)
 
+void remove (const std::string &key)
 
+uint64_t peek_first () const
 Get expiration time of soonest-to-expire entry.
 
+std::string pop_first ()
 
+iterator begin () const
 
+iterator end () const
 
+

Detailed Description

+

Expiration tracker keeps track of soonest-to-expire keys.

+

Member Function Documentation

+ +

◆ add()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + +
void crow::session::ExpirationTracker::add (std::string key,
uint64_t time 
)
+
+inline
+
+

Add key with time to tracker. If the key is already present, it will be updated

+ +
+
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1session_1_1_expiration_tracker.js b/1.2/reference/structcrow_1_1session_1_1_expiration_tracker.js new file mode 100644 index 000000000..aca90abae --- /dev/null +++ b/1.2/reference/structcrow_1_1session_1_1_expiration_tracker.js @@ -0,0 +1,11 @@ +var structcrow_1_1session_1_1_expiration_tracker = +[ + [ "DataPair", "structcrow_1_1session_1_1_expiration_tracker.html#a06ba0dbc04c5a2bb61546ac5e035aabd", null ], + [ "iterator", "structcrow_1_1session_1_1_expiration_tracker.html#aa4205f572bb2471fbf8ec813b3257441", null ], + [ "add", "structcrow_1_1session_1_1_expiration_tracker.html#a82f229b28c67ea4adfaae80db9628824", null ], + [ "begin", "structcrow_1_1session_1_1_expiration_tracker.html#a4e87b7767b8332dc2783dd201a5e76d8", null ], + [ "end", "structcrow_1_1session_1_1_expiration_tracker.html#a4630a7e3983bdbb2fe309eb95a4d65bd", null ], + [ "peek_first", "structcrow_1_1session_1_1_expiration_tracker.html#a3a41ed909b0162aaf0ba02725e468951", null ], + [ "pop_first", "structcrow_1_1session_1_1_expiration_tracker.html#a5eed24c3e7fe6102a29d22ea2461a8a0", null ], + [ "remove", "structcrow_1_1session_1_1_expiration_tracker.html#aa3aace2e65a445164d6b23d0df5531b6", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1session_1_1multi__value-members.html b/1.2/reference/structcrow_1_1session_1_1multi__value-members.html new file mode 100644 index 000000000..dfc3e0f1a --- /dev/null +++ b/1.2/reference/structcrow_1_1session_1_1multi__value-members.html @@ -0,0 +1,125 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::session::multi_value Member List
+
+
+ +

This is the complete list of members for crow::session::multi_value, including all inherited members.

+ + + + + + + +
from_json(const json::rvalue &) (defined in crow::session::multi_value)crow::session::multi_valueinlinestatic
get(const T &fallback) (defined in crow::session::multi_value)crow::session::multi_valueinline
json() const (defined in crow::session::multi_value)crow::session::multi_valueinline
set(T val) (defined in crow::session::multi_value)crow::session::multi_valueinline
string() const (defined in crow::session::multi_value)crow::session::multi_valueinline
v_ (defined in crow::session::multi_value)crow::session::multi_value
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1session_1_1multi__value.html b/1.2/reference/structcrow_1_1session_1_1multi__value.html new file mode 100644 index 000000000..3c08b78e1 --- /dev/null +++ b/1.2/reference/structcrow_1_1session_1_1multi__value.html @@ -0,0 +1,155 @@ + + + + + + + + Crow: crow::session::multi_value Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::session::multi_value Struct Reference
+
+
+ + + + + + + + + + + + +

+Public Member Functions

+json::wvalue json () const
 
+std::string string () const
 
+template<typename T , typename RT = wrap_mv_t<T>>
RT get (const T &fallback)
 
+template<typename T , typename RT = wrap_mv_t<T>>
void set (T val)
 
+ + + +

+Static Public Member Functions

+static multi_value from_json (const json::rvalue &)
 
+ + + +

+Public Attributes

+json::wvalue v_
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1session_1_1multi__value.js b/1.2/reference/structcrow_1_1session_1_1multi__value.js new file mode 100644 index 000000000..17c53b6f2 --- /dev/null +++ b/1.2/reference/structcrow_1_1session_1_1multi__value.js @@ -0,0 +1,8 @@ +var structcrow_1_1session_1_1multi__value = +[ + [ "get", "structcrow_1_1session_1_1multi__value.html#a62311206ffaa79b8677c596fe4fceba2", null ], + [ "json", "structcrow_1_1session_1_1multi__value.html#aa2ec92a7ee3d96e3d93d6ed4c00af013", null ], + [ "set", "structcrow_1_1session_1_1multi__value.html#aa311f75ec61c6db41d6a0067cbee2497", null ], + [ "string", "structcrow_1_1session_1_1multi__value.html#a6ce620f9168788c183563caf9725888e", null ], + [ "v_", "structcrow_1_1session_1_1multi__value.html#af9642bcf4498a91951d96ffe36afcd1e", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_send_message_type-members.html b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_send_message_type-members.html new file mode 100644 index 000000000..d4f71d2a1 --- /dev/null +++ b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_send_message_type-members.html @@ -0,0 +1,123 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ + + + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_send_message_type.html b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_send_message_type.html new file mode 100644 index 000000000..5385ef28c --- /dev/null +++ b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_send_message_type.html @@ -0,0 +1,143 @@ + + + + + + + + Crow: crow::websocket::Connection< Adaptor, Handler >::SendMessageType Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::websocket::Connection< Adaptor, Handler >::SendMessageType Struct Reference
+
+
+ + + + +

+Public Member Functions

+void operator() ()
 
+ + + + + + + +

+Public Attributes

+std::string payload
 
+Connectionself
 
+int opcode
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_send_message_type.js b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_send_message_type.js new file mode 100644 index 000000000..293e20b8a --- /dev/null +++ b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_send_message_type.js @@ -0,0 +1,7 @@ +var structcrow_1_1websocket_1_1_connection_1_1_send_message_type = +[ + [ "operator()", "structcrow_1_1websocket_1_1_connection_1_1_send_message_type.html#a704c71cf613d16f3f7680ad49ed39dce", null ], + [ "opcode", "structcrow_1_1websocket_1_1_connection_1_1_send_message_type.html#ab18d8c0e39286d68d49009d5037d384d", null ], + [ "payload", "structcrow_1_1websocket_1_1_connection_1_1_send_message_type.html#a1ec9dfedb35f3c386bb9b1091b439a59", null ], + [ "self", "structcrow_1_1websocket_1_1_connection_1_1_send_message_type.html#a7d907f8e4a436cf6c3ce8607138ab7da", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message-members.html b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message-members.html new file mode 100644 index 000000000..7febfa74c --- /dev/null +++ b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message-members.html @@ -0,0 +1,122 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ + + + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.html b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.html new file mode 100644 index 000000000..d6a34fb83 --- /dev/null +++ b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.html @@ -0,0 +1,140 @@ + + + + + + + + Crow: crow::websocket::Connection< Adaptor, Handler >::WeakWrappedMessage< Callable > Struct Template Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::websocket::Connection< Adaptor, Handler >::WeakWrappedMessage< Callable > Struct Template Reference
+
+
+ + + + +

+Public Member Functions

+void operator() ()
 
+ + + + + +

+Public Attributes

+Callable callable
 
+std::weak_ptr< void > watch
 
+
The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.js b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.js new file mode 100644 index 000000000..5948b4fdc --- /dev/null +++ b/1.2/reference/structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.js @@ -0,0 +1,6 @@ +var structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message = +[ + [ "operator()", "structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.html#a63dd07fc4d3cff7ce8ce240fbdb713d8", null ], + [ "callable", "structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.html#ad9fc0a2153553f39cd40ea1639e08179", null ], + [ "watch", "structcrow_1_1websocket_1_1_connection_1_1_weak_wrapped_message.html#ae78a48466c5a8d1bf6effa67352a54c6", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1websocket_1_1connection-members.html b/1.2/reference/structcrow_1_1websocket_1_1connection-members.html new file mode 100644 index 000000000..2229770bf --- /dev/null +++ b/1.2/reference/structcrow_1_1websocket_1_1connection-members.html @@ -0,0 +1,128 @@ + + + + + + + + Crow: Member List + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
crow::websocket::connection Member List
+
+
+ +

This is the complete list of members for crow::websocket::connection, including all inherited members.

+ + + + + + + + + + +
close(std::string const &msg="quit")=0 (defined in crow::websocket::connection)crow::websocket::connectionpure virtual
get_remote_ip()=0 (defined in crow::websocket::connection)crow::websocket::connectionpure virtual
send_binary(std::string msg)=0 (defined in crow::websocket::connection)crow::websocket::connectionpure virtual
send_ping(std::string msg)=0 (defined in crow::websocket::connection)crow::websocket::connectionpure virtual
send_pong(std::string msg)=0 (defined in crow::websocket::connection)crow::websocket::connectionpure virtual
send_text(std::string msg)=0 (defined in crow::websocket::connection)crow::websocket::connectionpure virtual
userdata(void *u) (defined in crow::websocket::connection)crow::websocket::connectioninline
userdata() (defined in crow::websocket::connection)crow::websocket::connectioninline
~connection()=default (defined in crow::websocket::connection)crow::websocket::connectionvirtual
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1websocket_1_1connection.html b/1.2/reference/structcrow_1_1websocket_1_1connection.html new file mode 100644 index 000000000..d9761bf71 --- /dev/null +++ b/1.2/reference/structcrow_1_1websocket_1_1connection.html @@ -0,0 +1,167 @@ + + + + + + + + Crow: crow::websocket::connection Struct Reference + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
crow::websocket::connection Struct Referenceabstract
+
+
+ +

A base class for websocket connection. + More...

+ +

#include <websocket.h>

+
+Inheritance diagram for crow::websocket::connection:
+
+
+ + +crow::websocket::Connection< Adaptor, Handler > + +
+ + + + + + + + + + + + + + + + + + +

+Public Member Functions

+virtual void send_binary (std::string msg)=0
 
+virtual void send_text (std::string msg)=0
 
+virtual void send_ping (std::string msg)=0
 
+virtual void send_pong (std::string msg)=0
 
+virtual void close (std::string const &msg="quit")=0
 
+virtual std::string get_remote_ip ()=0
 
+void userdata (void *u)
 
+void * userdata ()
 
+

Detailed Description

+

A base class for websocket connection.

+

The documentation for this struct was generated from the following file: +
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1websocket_1_1connection.js b/1.2/reference/structcrow_1_1websocket_1_1connection.js new file mode 100644 index 000000000..3b66bdcc3 --- /dev/null +++ b/1.2/reference/structcrow_1_1websocket_1_1connection.js @@ -0,0 +1,12 @@ +var structcrow_1_1websocket_1_1connection = +[ + [ "~connection", "structcrow_1_1websocket_1_1connection.html#acd6cced463c0da38b8503b38ea876c31", null ], + [ "close", "structcrow_1_1websocket_1_1connection.html#a0d1ac9e543d8e341979ed2b49c0fbaf7", null ], + [ "get_remote_ip", "structcrow_1_1websocket_1_1connection.html#a3980e17a609909a5e2140dd897fa704e", null ], + [ "send_binary", "structcrow_1_1websocket_1_1connection.html#ab2e8c749261a4c32fbf4f49a62f630e2", null ], + [ "send_ping", "structcrow_1_1websocket_1_1connection.html#af8acfc48d3e535f7658de77d08acc3e7", null ], + [ "send_pong", "structcrow_1_1websocket_1_1connection.html#a3ed7b66fc6b722fa9f56fb63a1e24ad5", null ], + [ "send_text", "structcrow_1_1websocket_1_1connection.html#a0d405c61d1476dd3958acac216b148a3", null ], + [ "userdata", "structcrow_1_1websocket_1_1connection.html#a301af57187b6d7419d1825c8a15c22f6", null ], + [ "userdata", "structcrow_1_1websocket_1_1connection.html#a75b25cfa1f5f8fd3bbae01b5637097f6", null ] +]; \ No newline at end of file diff --git a/1.2/reference/structcrow_1_1websocket_1_1connection.png b/1.2/reference/structcrow_1_1websocket_1_1connection.png new file mode 100644 index 000000000..7aba28f7a Binary files /dev/null and b/1.2/reference/structcrow_1_1websocket_1_1connection.png differ diff --git a/1.2/reference/sync_off.png b/1.2/reference/sync_off.png new file mode 100644 index 000000000..3b443fc62 Binary files /dev/null and b/1.2/reference/sync_off.png differ diff --git a/1.2/reference/sync_on.png b/1.2/reference/sync_on.png new file mode 100644 index 000000000..e08320fb6 Binary files /dev/null and b/1.2/reference/sync_on.png differ diff --git a/1.2/reference/tab_a.png b/1.2/reference/tab_a.png new file mode 100644 index 000000000..3b725c41c Binary files /dev/null and b/1.2/reference/tab_a.png differ diff --git a/1.2/reference/tab_b.png b/1.2/reference/tab_b.png new file mode 100644 index 000000000..e2b4a8638 Binary files /dev/null and b/1.2/reference/tab_b.png differ diff --git a/1.2/reference/tab_h.png b/1.2/reference/tab_h.png new file mode 100644 index 000000000..fd5cb7054 Binary files /dev/null and b/1.2/reference/tab_h.png differ diff --git a/1.2/reference/tab_s.png b/1.2/reference/tab_s.png new file mode 100644 index 000000000..ab478c95b Binary files /dev/null and b/1.2/reference/tab_s.png differ diff --git a/1.2/reference/tabs.css b/1.2/reference/tabs.css new file mode 100644 index 000000000..7d45d36c1 --- /dev/null +++ b/1.2/reference/tabs.css @@ -0,0 +1 @@ +.sm{position:relative;z-index:9999}.sm,.sm ul,.sm li{display:block;list-style:none;margin:0;padding:0;line-height:normal;direction:ltr;text-align:left;-webkit-tap-highlight-color:rgba(0,0,0,0)}.sm-rtl,.sm-rtl ul,.sm-rtl li{direction:rtl;text-align:right}.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6{margin:0;padding:0}.sm ul{display:none}.sm li,.sm a{position:relative}.sm a{display:block}.sm a.disabled{cursor:not-allowed}.sm:after{content:"\00a0";display:block;height:0;font:0px/0 serif;clear:both;visibility:hidden;overflow:hidden}.sm,.sm *,.sm *:before,.sm *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sm-dox{background-image:url("tab_b.png")}.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active{padding:0px 12px;padding-right:43px;font-family:"Lucida Grande","Geneva","Helvetica",Arial,sans-serif;font-size:13px;font-weight:bold;line-height:36px;text-decoration:none;text-shadow:0px 1px 1px rgba(255,255,255,0.9);color:#283A5D;outline:none}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox a.current{color:#D23600}.sm-dox a.disabled{color:#bbb}.sm-dox a span.sub-arrow{position:absolute;top:50%;margin-top:-14px;left:auto;right:3px;width:28px;height:28px;overflow:hidden;font:bold 12px/28px monospace !important;text-align:center;text-shadow:none;background:rgba(255,255,255,0.5);border-radius:5px}.sm-dox a.highlighted span.sub-arrow:before{display:block;content:'-'}.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a{border-radius:5px 5px 0 0}.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul{border-radius:0 0 5px 5px}.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted{border-radius:0}.sm-dox ul{background:rgba(162,162,162,0.1)}.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active{font-size:12px;border-left:8px solid transparent;line-height:36px;text-shadow:none;background-color:white;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active{border-left:16px solid transparent}.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active{border-left:24px solid transparent}.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active{border-left:32px solid transparent}.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active{border-left:40px solid transparent}@media (min-width: 768px){.sm-dox ul{position:absolute;width:12em}.sm-dox li{float:left}.sm-dox.sm-rtl li{float:right}.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none}.sm-dox a{white-space:nowrap}.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal}.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a{white-space:nowrap}.sm-dox{padding:0 10px;background-image:url("tab_b.png");line-height:36px}.sm-dox a span.sub-arrow{top:50%;margin-top:-2px;right:12px;width:0;height:0;border-width:4px;border-style:solid dashed dashed dashed;border-color:#283A5D transparent transparent transparent;background:transparent;border-radius:0}.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted{padding:0px 12px;background-image:url("tab_s.png");background-repeat:no-repeat;background-position:right;border-radius:0 !important}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox a:hover span.sub-arrow{border-color:#fff transparent transparent transparent}.sm-dox a.has-submenu{padding-right:24px}.sm-dox li{border-top:0}.sm-dox>li>ul:before,.sm-dox>li>ul:after{content:'';position:absolute;top:-18px;left:30px;width:0;height:0;overflow:hidden;border-width:9px;border-style:dashed dashed solid dashed;border-color:transparent transparent #bbb transparent}.sm-dox>li>ul:after{top:-16px;left:31px;border-width:8px;border-color:transparent transparent #fff transparent}.sm-dox ul{border:1px solid #bbb;padding:5px 0;background:#fff;border-radius:5px !important;box-shadow:0 5px 9px rgba(0,0,0,0.2)}.sm-dox ul a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-color:transparent transparent transparent #555;border-style:dashed dashed dashed solid}.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted{color:#555;background-image:none;border:0 !important;color:#555;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:#fff;text-shadow:0px 1px 1px #000}.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent #fff}.sm-dox span.scroll-up,.sm-dox span.scroll-down{position:absolute;display:none;visibility:hidden;overflow:hidden;background:#fff;height:36px}.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover{background:#eee}.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow{border-color:transparent transparent #D23600 transparent}.sm-dox span.scroll-down:hover span.scroll-down-arrow{border-color:#D23600 transparent transparent transparent}.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow{position:absolute;top:0;left:50%;margin-left:-6px;width:0;height:0;overflow:hidden;border-width:6px;border-style:dashed dashed solid dashed;border-color:transparent transparent #555 transparent}.sm-dox span.scroll-down-arrow{top:8px;border-style:solid dashed dashed dashed;border-color:#555 transparent transparent transparent}.sm-dox.sm-rtl a.has-submenu{padding-right:12px;padding-left:24px}.sm-dox.sm-rtl a span.sub-arrow{right:auto;left:12px}.sm-dox.sm-rtl.sm-vertical a.has-submenu{padding:10px 20px}.sm-dox.sm-rtl.sm-vertical a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-rtl>li>ul:before{left:auto;right:30px}.sm-dox.sm-rtl>li>ul:after{left:auto;right:31px}.sm-dox.sm-rtl ul a.has-submenu{padding:10px 20px !important}.sm-dox.sm-rtl ul a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-vertical{padding:10px 0;border-radius:5px}.sm-dox.sm-vertical a{padding:10px 20px}.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted{background:#fff}.sm-dox.sm-vertical a.disabled{background-image:url("tab_b.png")}.sm-dox.sm-vertical a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-style:dashed dashed dashed solid;border-color:transparent transparent transparent #555}.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after{display:none}.sm-dox.sm-vertical ul a{padding:10px 20px}.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted{background:#eee}.sm-dox.sm-vertical ul a.disabled{background:#fff}} diff --git a/1.2/reference/task__timer_8h_source.html b/1.2/reference/task__timer_8h_source.html new file mode 100644 index 000000000..3076dee7b --- /dev/null +++ b/1.2/reference/task__timer_8h_source.html @@ -0,0 +1,271 @@ + + + + + + + + Crow: include/crow/task_timer.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
task_timer.h
+
+
+
1 #pragma once
+
2 
+
3 #ifdef CROW_USE_BOOST
+
4 #include <boost/asio.hpp>
+
5 #include <boost/asio/basic_waitable_timer.hpp>
+
6 #else
+
7 #ifndef ASIO_STANDALONE
+
8 #define ASIO_STANDALONE
+
9 #endif
+
10 #include <asio.hpp>
+
11 #include <asio/basic_waitable_timer.hpp>
+
12 #endif
+
13 
+
14 #include <chrono>
+
15 #include <functional>
+
16 #include <map>
+
17 #include <vector>
+
18 
+
19 #include "crow/logging.h"
+
20 
+
21 namespace crow
+
22 {
+
23 #ifdef CROW_USE_BOOST
+
24  namespace asio = boost::asio;
+
25  using error_code = boost::system::error_code;
+
26 #else
+
27  using error_code = asio::error_code;
+
28 #endif
+
29  namespace detail
+
30  {
+
31 
+
32  /// A class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 second.
+
33  class task_timer
+
34  {
+
35  public:
+
36  using task_type = std::function<void()>;
+
37  using identifier_type = size_t;
+
38 
+
39  private:
+
40  using clock_type = std::chrono::steady_clock;
+
41  using time_type = clock_type::time_point;
+
42 
+
43  public:
+
44  task_timer(asio::io_service& io_service):
+
45  io_service_(io_service), timer_(io_service_)
+
46  {
+
47  timer_.expires_after(std::chrono::seconds(1));
+
48  timer_.async_wait(
+
49  std::bind(&task_timer::tick_handler, this, std::placeholders::_1));
+
50  }
+
51 
+
52  ~task_timer() { timer_.cancel(); }
+
53 
+
54  void cancel(identifier_type id)
+
55  {
+
56  tasks_.erase(id);
+
57  CROW_LOG_DEBUG << "task_timer cancelled: " << this << ' ' << id;
+
58  }
+
59 
+
60  /// Schedule the given task to be executed after the default amount of ticks.
+
61 
+
62  ///
+
63  /// \return identifier_type Used to cancel the thread.
+
64  /// It is not bound to this task_timer instance and in some cases could lead to
+
65  /// undefined behavior if used with other task_timer objects or after the task
+
66  /// has been successfully executed.
+
67  identifier_type schedule(const task_type& task)
+
68  {
+
69  tasks_.insert(
+
70  {++highest_id_,
+
71  {clock_type::now() + std::chrono::seconds(get_default_timeout()),
+
72  task}});
+
73  CROW_LOG_DEBUG << "task_timer scheduled: " << this << ' ' << highest_id_;
+
74  return highest_id_;
+
75  }
+
76 
+
77  /// Schedule the given task to be executed after the given time.
+
78 
+
79  ///
+
80  /// \param timeout The amount of ticks (seconds) to wait before execution.
+
81  ///
+
82  /// \return identifier_type Used to cancel the thread.
+
83  /// It is not bound to this task_timer instance and in some cases could lead to
+
84  /// undefined behavior if used with other task_timer objects or after the task
+
85  /// has been successfully executed.
+
86  identifier_type schedule(const task_type& task, std::uint8_t timeout)
+
87  {
+
88  tasks_.insert({++highest_id_,
+
89  {clock_type::now() + std::chrono::seconds(timeout), task}});
+
90  CROW_LOG_DEBUG << "task_timer scheduled: " << this << ' ' << highest_id_;
+
91  return highest_id_;
+
92  }
+
93 
+
94  /// Set the default timeout for this task_timer instance. (Default: 5)
+
95 
+
96  ///
+
97  /// \param timeout The amount of ticks (seconds) to wait before execution.
+
98  void set_default_timeout(std::uint8_t timeout) { default_timeout_ = timeout; }
+
99 
+
100  /// Get the default timeout. (Default: 5)
+
101  std::uint8_t get_default_timeout() const { return default_timeout_; }
+
102 
+
103  private:
+
104  void process_tasks()
+
105  {
+
106  time_type current_time = clock_type::now();
+
107  std::vector<identifier_type> finished_tasks;
+
108 
+
109  for (const auto& task : tasks_)
+
110  {
+
111  if (task.second.first < current_time)
+
112  {
+
113  (task.second.second)();
+
114  finished_tasks.push_back(task.first);
+
115  CROW_LOG_DEBUG << "task_timer called: " << this << ' ' << task.first;
+
116  }
+
117  }
+
118 
+
119  for (const auto& task : finished_tasks)
+
120  tasks_.erase(task);
+
121 
+
122  // If no task is currently scheduled, reset the issued ids back to 0.
+
123  if (tasks_.empty()) highest_id_ = 0;
+
124  }
+
125 
+
126  void tick_handler(const error_code& ec)
+
127  {
+
128  if (ec) return;
+
129 
+
130  process_tasks();
+
131 
+
132  timer_.expires_after(std::chrono::seconds(1));
+
133  timer_.async_wait(
+
134  std::bind(&task_timer::tick_handler, this, std::placeholders::_1));
+
135  }
+
136 
+
137  private:
+
138  std::uint8_t default_timeout_{5};
+
139  asio::io_service& io_service_;
+
140  asio::basic_waitable_timer<clock_type> timer_;
+
141  std::map<identifier_type, std::pair<time_type, task_type>> tasks_;
+
142 
+
143  // A continuosly increasing number to be issued to threads to identify them.
+
144  // If no tasks are scheduled, it will be reset to 0.
+
145  identifier_type highest_id_{0};
+
146  };
+
147  } // namespace detail
+
148 } // namespace crow
+
A class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 ...
Definition: task_timer.h:34
+
identifier_type schedule(const task_type &task, std::uint8_t timeout)
Schedule the given task to be executed after the given time.
Definition: task_timer.h:86
+
void set_default_timeout(std::uint8_t timeout)
Set the default timeout for this task_timer instance. (Default: 5)
Definition: task_timer.h:98
+
identifier_type schedule(const task_type &task)
Schedule the given task to be executed after the default amount of ticks.
Definition: task_timer.h:67
+
std::uint8_t get_default_timeout() const
Get the default timeout. (Default: 5)
Definition: task_timer.h:101
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/utf-8_8h_source.html b/1.2/reference/utf-8_8h_source.html new file mode 100644 index 000000000..b5e858bea --- /dev/null +++ b/1.2/reference/utf-8_8h_source.html @@ -0,0 +1,150 @@ + + + + + + + + Crow: include/crow/middlewares/utf-8.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
utf-8.h
+
+
+
1 #pragma once
+
2 #include "crow/http_request.h"
+
3 #include "crow/http_response.h"
+
4 
+
5 namespace crow
+
6 {
+
7 
+
8  struct UTF8
+
9  {
+
10  struct context
+
11  {};
+
12 
+
13  void before_handle(request& /*req*/, response& /*res*/, context& /*ctx*/)
+
14  {}
+
15 
+
16  void after_handle(request& /*req*/, response& res, context& /*ctx*/)
+
17  {
+
18  if (get_header_value(res.headers, "Content-Type").empty())
+
19  {
+
20  res.set_header("Content-Type", "text/plain; charset=utf-8");
+
21  }
+
22  }
+
23  };
+
24 
+
25 } // namespace crow
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
const std::string & get_header_value(const T &headers, const std::string &key)
Find and return the value associated with the key. (returns an empty string if nothing is found)
Definition: http_request.h:24
+
Definition: utf-8.h:11
+
Definition: utf-8.h:9
+
An HTTP request.
Definition: http_request.h:36
+
HTTP response.
Definition: http_response.h:34
+
void set_header(std::string key, std::string value)
Set the value of an existing header in the response.
Definition: http_response.h:51
+
ci_map headers
HTTP headers.
Definition: http_response.h:42
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/utility_8h_source.html b/1.2/reference/utility_8h_source.html new file mode 100644 index 000000000..126476ab4 --- /dev/null +++ b/1.2/reference/utility_8h_source.html @@ -0,0 +1,1028 @@ + + + + + + + + Crow: include/crow/utility.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
utility.h
+
+
+
1 #pragma once
+
2 
+
3 #include <cstdint>
+
4 #include <stdexcept>
+
5 #include <tuple>
+
6 #include <type_traits>
+
7 #include <cstring>
+
8 #include <cctype>
+
9 #include <functional>
+
10 #include <string>
+
11 #include <sstream>
+
12 #include <unordered_map>
+
13 #include <random>
+
14 #include <algorithm>
+
15 
+
16 #include "crow/settings.h"
+
17 
+
18 #if defined(CROW_CAN_USE_CPP17) && !defined(CROW_FILESYSTEM_IS_EXPERIMENTAL)
+
19 #include <filesystem>
+
20 #endif
+
21 
+
22 // TODO(EDev): Adding C++20's [[likely]] and [[unlikely]] attributes might be useful
+
23 #if defined(__GNUG__) || defined(__clang__)
+
24 #define CROW_LIKELY(X) __builtin_expect(!!(X), 1)
+
25 #define CROW_UNLIKELY(X) __builtin_expect(!!(X), 0)
+
26 #else
+
27 #define CROW_LIKELY(X) (X)
+
28 #define CROW_UNLIKELY(X) (X)
+
29 #endif
+
30 
+
31 namespace crow
+
32 {
+
33  /// @cond SKIP
+
34  namespace black_magic
+
35  {
+
36 #ifndef CROW_MSVC_WORKAROUND
+
37  /// Out of Range Exception for const_str
+
38  struct OutOfRange
+
39  {
+
40  OutOfRange(unsigned /*pos*/, unsigned /*length*/) {}
+
41  };
+
42  /// Helper function to throw an exception if i is larger than len
+
43  constexpr unsigned requires_in_range(unsigned i, unsigned len)
+
44  {
+
45  return i >= len ? throw OutOfRange(i, len) : i;
+
46  }
+
47 
+
48  /// A constant string implementation.
+
49  class const_str
+
50  {
+
51  const char* const begin_;
+
52  unsigned size_;
+
53 
+
54  public:
+
55  template<unsigned N>
+
56  constexpr const_str(const char (&arr)[N]):
+
57  begin_(arr), size_(N - 1)
+
58  {
+
59  static_assert(N >= 1, "not a string literal");
+
60  }
+
61  constexpr char operator[](unsigned i) const
+
62  {
+
63  return requires_in_range(i, size_), begin_[i];
+
64  }
+
65 
+
66  constexpr operator const char*() const
+
67  {
+
68  return begin_;
+
69  }
+
70 
+
71  constexpr const char* begin() const { return begin_; }
+
72  constexpr const char* end() const { return begin_ + size_; }
+
73 
+
74  constexpr unsigned size() const
+
75  {
+
76  return size_;
+
77  }
+
78  };
+
79 
+
80  constexpr unsigned find_closing_tag(const_str s, unsigned p)
+
81  {
+
82  return s[p] == '>' ? p : find_closing_tag(s, p + 1);
+
83  }
+
84 
+
85  /// Check that the CROW_ROUTE string is valid
+
86  constexpr bool is_valid(const_str s, unsigned i = 0, int f = 0)
+
87  {
+
88  return i == s.size() ? f == 0 :
+
89  f < 0 || f >= 2 ? false :
+
90  s[i] == '<' ? is_valid(s, i + 1, f + 1) :
+
91  s[i] == '>' ? is_valid(s, i + 1, f - 1) :
+
92  is_valid(s, i + 1, f);
+
93  }
+
94 
+
95  constexpr bool is_equ_p(const char* a, const char* b, unsigned n)
+
96  {
+
97  return *a == 0 && *b == 0 && n == 0 ? true :
+
98  (*a == 0 || *b == 0) ? false :
+
99  n == 0 ? true :
+
100  *a != *b ? false :
+
101  is_equ_p(a + 1, b + 1, n - 1);
+
102  }
+
103 
+
104  constexpr bool is_equ_n(const_str a, unsigned ai, const_str b, unsigned bi, unsigned n)
+
105  {
+
106  return ai + n > a.size() || bi + n > b.size() ? false :
+
107  n == 0 ? true :
+
108  a[ai] != b[bi] ? false :
+
109  is_equ_n(a, ai + 1, b, bi + 1, n - 1);
+
110  }
+
111 
+
112  constexpr bool is_int(const_str s, unsigned i)
+
113  {
+
114  return is_equ_n(s, i, "<int>", 0, 5);
+
115  }
+
116 
+
117  constexpr bool is_uint(const_str s, unsigned i)
+
118  {
+
119  return is_equ_n(s, i, "<uint>", 0, 6);
+
120  }
+
121 
+
122  constexpr bool is_float(const_str s, unsigned i)
+
123  {
+
124  return is_equ_n(s, i, "<float>", 0, 7) ||
+
125  is_equ_n(s, i, "<double>", 0, 8);
+
126  }
+
127 
+
128  constexpr bool is_str(const_str s, unsigned i)
+
129  {
+
130  return is_equ_n(s, i, "<str>", 0, 5) ||
+
131  is_equ_n(s, i, "<string>", 0, 8);
+
132  }
+
133 
+
134  constexpr bool is_path(const_str s, unsigned i)
+
135  {
+
136  return is_equ_n(s, i, "<path>", 0, 6);
+
137  }
+
138 #endif
+
139  template<typename T>
+
140  struct parameter_tag
+
141  {
+
142  static const int value = 0;
+
143  };
+
144 #define CROW_INTERNAL_PARAMETER_TAG(t, i) \
+
145  template<> \
+
146  struct parameter_tag<t> \
+
147  { \
+
148  static const int value = i; \
+
149  }
+
150  CROW_INTERNAL_PARAMETER_TAG(int, 1);
+
151  CROW_INTERNAL_PARAMETER_TAG(char, 1);
+
152  CROW_INTERNAL_PARAMETER_TAG(short, 1);
+
153  CROW_INTERNAL_PARAMETER_TAG(long, 1);
+
154  CROW_INTERNAL_PARAMETER_TAG(long long, 1);
+
155  CROW_INTERNAL_PARAMETER_TAG(unsigned int, 2);
+
156  CROW_INTERNAL_PARAMETER_TAG(unsigned char, 2);
+
157  CROW_INTERNAL_PARAMETER_TAG(unsigned short, 2);
+
158  CROW_INTERNAL_PARAMETER_TAG(unsigned long, 2);
+
159  CROW_INTERNAL_PARAMETER_TAG(unsigned long long, 2);
+
160  CROW_INTERNAL_PARAMETER_TAG(double, 3);
+
161  CROW_INTERNAL_PARAMETER_TAG(std::string, 4);
+
162 #undef CROW_INTERNAL_PARAMETER_TAG
+
163  template<typename... Args>
+
164  struct compute_parameter_tag_from_args_list;
+
165 
+
166  template<>
+
167  struct compute_parameter_tag_from_args_list<>
+
168  {
+
169  static const int value = 0;
+
170  };
+
171 
+
172  template<typename Arg, typename... Args>
+
173  struct compute_parameter_tag_from_args_list<Arg, Args...>
+
174  {
+
175  static const int sub_value =
+
176  compute_parameter_tag_from_args_list<Args...>::value;
+
177  static const int value =
+
178  parameter_tag<typename std::decay<Arg>::type>::value ? sub_value * 6 + parameter_tag<typename std::decay<Arg>::type>::value : sub_value;
+
179  };
+
180 
+
181  static inline bool is_parameter_tag_compatible(uint64_t a, uint64_t b)
+
182  {
+
183  if (a == 0)
+
184  return b == 0;
+
185  if (b == 0)
+
186  return a == 0;
+
187  int sa = a % 6;
+
188  int sb = a % 6;
+
189  if (sa == 5) sa = 4;
+
190  if (sb == 5) sb = 4;
+
191  if (sa != sb)
+
192  return false;
+
193  return is_parameter_tag_compatible(a / 6, b / 6);
+
194  }
+
195 
+
196  static inline unsigned find_closing_tag_runtime(const char* s, unsigned p)
+
197  {
+
198  return s[p] == 0 ? throw std::runtime_error("unmatched tag <") :
+
199  s[p] == '>' ? p :
+
200  find_closing_tag_runtime(s, p + 1);
+
201  }
+
202 
+
203  static inline uint64_t get_parameter_tag_runtime(const char* s, unsigned p = 0)
+
204  {
+
205  return s[p] == 0 ? 0 :
+
206  s[p] == '<' ? (
+
207  std::strncmp(s + p, "<int>", 5) == 0 ? get_parameter_tag_runtime(s, find_closing_tag_runtime(s, p)) * 6 + 1 :
+
208  std::strncmp(s + p, "<uint>", 6) == 0 ? get_parameter_tag_runtime(s, find_closing_tag_runtime(s, p)) * 6 + 2 :
+
209  (std::strncmp(s + p, "<float>", 7) == 0 ||
+
210  std::strncmp(s + p, "<double>", 8) == 0) ?
+
211  get_parameter_tag_runtime(s, find_closing_tag_runtime(s, p)) * 6 + 3 :
+
212  (std::strncmp(s + p, "<str>", 5) == 0 ||
+
213  std::strncmp(s + p, "<string>", 8) == 0) ?
+
214  get_parameter_tag_runtime(s, find_closing_tag_runtime(s, p)) * 6 + 4 :
+
215  std::strncmp(s + p, "<path>", 6) == 0 ? get_parameter_tag_runtime(s, find_closing_tag_runtime(s, p)) * 6 + 5 :
+
216  throw std::runtime_error("invalid parameter type")) :
+
217  get_parameter_tag_runtime(s, p + 1);
+
218  }
+
219 #ifndef CROW_MSVC_WORKAROUND
+
220  constexpr uint64_t get_parameter_tag(const_str s, unsigned p = 0)
+
221  {
+
222  return p == s.size() ? 0 :
+
223  s[p] == '<' ? (
+
224  is_int(s, p) ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 1 :
+
225  is_uint(s, p) ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 2 :
+
226  is_float(s, p) ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 3 :
+
227  is_str(s, p) ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 4 :
+
228  is_path(s, p) ? get_parameter_tag(s, find_closing_tag(s, p)) * 6 + 5 :
+
229  throw std::runtime_error("invalid parameter type")) :
+
230  get_parameter_tag(s, p + 1);
+
231  }
+
232 #endif
+
233 
+
234  template<typename... T>
+
235  struct S
+
236  {
+
237  template<typename U>
+
238  using push = S<U, T...>;
+
239  template<typename U>
+
240  using push_back = S<T..., U>;
+
241  template<template<typename... Args> class U>
+
242  using rebind = U<T...>;
+
243  };
+
244 
+
245  // Check whether the template function can be called with specific arguments
+
246  template<typename F, typename Set>
+
247  struct CallHelper;
+
248  template<typename F, typename... Args>
+
249  struct CallHelper<F, S<Args...>>
+
250  {
+
251  template<typename F1, typename... Args1, typename = decltype(std::declval<F1>()(std::declval<Args1>()...))>
+
252  static char __test(int);
+
253 
+
254  template<typename...>
+
255  static int __test(...);
+
256 
+
257  static constexpr bool value = sizeof(__test<F, Args...>(0)) == sizeof(char);
+
258  };
+
259 
+
260  // Check Tuple contains type T
+
261  template<typename T, typename Tuple>
+
262  struct has_type;
+
263 
+
264  template<typename T>
+
265  struct has_type<T, std::tuple<>> : std::false_type
+
266  {};
+
267 
+
268  template<typename T, typename U, typename... Ts>
+
269  struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>>
+
270  {};
+
271 
+
272  template<typename T, typename... Ts>
+
273  struct has_type<T, std::tuple<T, Ts...>> : std::true_type
+
274  {};
+
275 
+
276  // Find index of type in tuple
+
277  template<class T, class Tuple>
+
278  struct tuple_index;
+
279 
+
280  template<class T, class... Types>
+
281  struct tuple_index<T, std::tuple<T, Types...>>
+
282  {
+
283  static const int value = 0;
+
284  };
+
285 
+
286  template<class T, class U, class... Types>
+
287  struct tuple_index<T, std::tuple<U, Types...>>
+
288  {
+
289  static const int value = 1 + tuple_index<T, std::tuple<Types...>>::value;
+
290  };
+
291 
+
292  // Extract element from forward tuple or get default
+
293 #ifdef CROW_CAN_USE_CPP14
+
294  template<typename T, typename Tup>
+
295  typename std::enable_if<has_type<T&, Tup>::value, typename std::decay<T>::type&&>::type
+
296  tuple_extract(Tup& tup)
+
297  {
+
298  return std::move(std::get<T&>(tup));
+
299  }
+
300 #else
+
301  template<typename T, typename Tup>
+
302  typename std::enable_if<has_type<T&, Tup>::value, T&&>::type
+
303  tuple_extract(Tup& tup)
+
304  {
+
305  return std::move(std::get<tuple_index<T&, Tup>::value>(tup));
+
306  }
+
307 #endif
+
308 
+
309  template<typename T, typename Tup>
+
310  typename std::enable_if<!has_type<T&, Tup>::value, T>::type
+
311  tuple_extract(Tup&)
+
312  {
+
313  return T{};
+
314  }
+
315 
+
316  // Kind of fold expressions in C++11
+
317  template<bool...>
+
318  struct bool_pack;
+
319  template<bool... bs>
+
320  using all_true = std::is_same<bool_pack<bs..., true>, bool_pack<true, bs...>>;
+
321 
+
322  template<int N>
+
323  struct single_tag_to_type
+
324  {};
+
325 
+
326  template<>
+
327  struct single_tag_to_type<1>
+
328  {
+
329  using type = int64_t;
+
330  };
+
331 
+
332  template<>
+
333  struct single_tag_to_type<2>
+
334  {
+
335  using type = uint64_t;
+
336  };
+
337 
+
338  template<>
+
339  struct single_tag_to_type<3>
+
340  {
+
341  using type = double;
+
342  };
+
343 
+
344  template<>
+
345  struct single_tag_to_type<4>
+
346  {
+
347  using type = std::string;
+
348  };
+
349 
+
350  template<>
+
351  struct single_tag_to_type<5>
+
352  {
+
353  using type = std::string;
+
354  };
+
355 
+
356 
+
357  template<uint64_t Tag>
+
358  struct arguments
+
359  {
+
360  using subarguments = typename arguments<Tag / 6>::type;
+
361  using type =
+
362  typename subarguments::template push<typename single_tag_to_type<Tag % 6>::type>;
+
363  };
+
364 
+
365  template<>
+
366  struct arguments<0>
+
367  {
+
368  using type = S<>;
+
369  };
+
370 
+
371  template<typename... T>
+
372  struct last_element_type
+
373  {
+
374  using type = typename std::tuple_element<sizeof...(T) - 1, std::tuple<T...>>::type;
+
375  };
+
376 
+
377 
+
378  template<>
+
379  struct last_element_type<>
+
380  {};
+
381 
+
382 
+
383  // from http://stackoverflow.com/questions/13072359/c11-compile-time-array-with-logarithmic-evaluation-depth
+
384  template<class T>
+
385  using Invoke = typename T::type;
+
386 
+
387  template<unsigned...>
+
388  struct seq
+
389  {
+
390  using type = seq;
+
391  };
+
392 
+
393  template<class S1, class S2>
+
394  struct concat;
+
395 
+
396  template<unsigned... I1, unsigned... I2>
+
397  struct concat<seq<I1...>, seq<I2...>> : seq<I1..., (sizeof...(I1) + I2)...>
+
398  {};
+
399 
+
400  template<class S1, class S2>
+
401  using Concat = Invoke<concat<S1, S2>>;
+
402 
+
403  template<unsigned N>
+
404  struct gen_seq;
+
405  template<unsigned N>
+
406  using GenSeq = Invoke<gen_seq<N>>;
+
407 
+
408  template<unsigned N>
+
409  struct gen_seq : Concat<GenSeq<N / 2>, GenSeq<N - N / 2>>
+
410  {};
+
411 
+
412  template<>
+
413  struct gen_seq<0> : seq<>
+
414  {};
+
415  template<>
+
416  struct gen_seq<1> : seq<0>
+
417  {};
+
418 
+
419  template<typename Seq, typename Tuple>
+
420  struct pop_back_helper;
+
421 
+
422  template<unsigned... N, typename Tuple>
+
423  struct pop_back_helper<seq<N...>, Tuple>
+
424  {
+
425  template<template<typename... Args> class U>
+
426  using rebind = U<typename std::tuple_element<N, Tuple>::type...>;
+
427  };
+
428 
+
429  template<typename... T>
+
430  struct pop_back //: public pop_back_helper<typename gen_seq<sizeof...(T)-1>::type, std::tuple<T...>>
+
431  {
+
432  template<template<typename... Args> class U>
+
433  using rebind = typename pop_back_helper<typename gen_seq<sizeof...(T) - 1>::type, std::tuple<T...>>::template rebind<U>;
+
434  };
+
435 
+
436  template<>
+
437  struct pop_back<>
+
438  {
+
439  template<template<typename... Args> class U>
+
440  using rebind = U<>;
+
441  };
+
442 
+
443  // from http://stackoverflow.com/questions/2118541/check-if-c0x-parameter-pack-contains-a-type
+
444  template<typename Tp, typename... List>
+
445  struct contains : std::true_type
+
446  {};
+
447 
+
448  template<typename Tp, typename Head, typename... Rest>
+
449  struct contains<Tp, Head, Rest...> : std::conditional<std::is_same<Tp, Head>::value, std::true_type, contains<Tp, Rest...>>::type
+
450  {};
+
451 
+
452  template<typename Tp>
+
453  struct contains<Tp> : std::false_type
+
454  {};
+
455 
+
456  template<typename T>
+
457  struct empty_context
+
458  {};
+
459 
+
460  template<typename T>
+
461  struct promote
+
462  {
+
463  using type = T;
+
464  };
+
465 
+
466 #define CROW_INTERNAL_PROMOTE_TYPE(t1, t2) \
+
467  template<> \
+
468  struct promote<t1> \
+
469  { \
+
470  using type = t2; \
+
471  }
+
472 
+
473  CROW_INTERNAL_PROMOTE_TYPE(char, int64_t);
+
474  CROW_INTERNAL_PROMOTE_TYPE(short, int64_t);
+
475  CROW_INTERNAL_PROMOTE_TYPE(int, int64_t);
+
476  CROW_INTERNAL_PROMOTE_TYPE(long, int64_t);
+
477  CROW_INTERNAL_PROMOTE_TYPE(long long, int64_t);
+
478  CROW_INTERNAL_PROMOTE_TYPE(unsigned char, uint64_t);
+
479  CROW_INTERNAL_PROMOTE_TYPE(unsigned short, uint64_t);
+
480  CROW_INTERNAL_PROMOTE_TYPE(unsigned int, uint64_t);
+
481  CROW_INTERNAL_PROMOTE_TYPE(unsigned long, uint64_t);
+
482  CROW_INTERNAL_PROMOTE_TYPE(unsigned long long, uint64_t);
+
483  CROW_INTERNAL_PROMOTE_TYPE(float, double);
+
484 #undef CROW_INTERNAL_PROMOTE_TYPE
+
485 
+
486  template<typename T>
+
487  using promote_t = typename promote<T>::type;
+
488 
+
489  } // namespace black_magic
+
490 
+
491  namespace detail
+
492  {
+
493 
+
494  template<class T, std::size_t N, class... Args>
+
495  struct get_index_of_element_from_tuple_by_type_impl
+
496  {
+
497  static constexpr auto value = N;
+
498  };
+
499 
+
500  template<class T, std::size_t N, class... Args>
+
501  struct get_index_of_element_from_tuple_by_type_impl<T, N, T, Args...>
+
502  {
+
503  static constexpr auto value = N;
+
504  };
+
505 
+
506  template<class T, std::size_t N, class U, class... Args>
+
507  struct get_index_of_element_from_tuple_by_type_impl<T, N, U, Args...>
+
508  {
+
509  static constexpr auto value = get_index_of_element_from_tuple_by_type_impl<T, N + 1, Args...>::value;
+
510  };
+
511  } // namespace detail
+
512 
+
513  namespace utility
+
514  {
+
515  template<class T, class... Args>
+
516  T& get_element_by_type(std::tuple<Args...>& t)
+
517  {
+
518  return std::get<detail::get_index_of_element_from_tuple_by_type_impl<T, 0, Args...>::value>(t);
+
519  }
+
520 
+
521  template<typename T>
+
522  struct function_traits;
+
523 
+
524 #ifndef CROW_MSVC_WORKAROUND
+
525  template<typename T>
+
526  struct function_traits : public function_traits<decltype(&T::operator())>
+
527  {
+
528  using parent_t = function_traits<decltype(&T::operator())>;
+
529  static const size_t arity = parent_t::arity;
+
530  using result_type = typename parent_t::result_type;
+
531  template<size_t i>
+
532  using arg = typename parent_t::template arg<i>;
+
533  };
+
534 #endif
+
535 
+
536  template<typename ClassType, typename R, typename... Args>
+
537  struct function_traits<R (ClassType::*)(Args...) const>
+
538  {
+
539  static const size_t arity = sizeof...(Args);
+
540 
+
541  typedef R result_type;
+
542 
+
543  template<size_t i>
+
544  using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
+
545  };
+
546 
+
547  template<typename ClassType, typename R, typename... Args>
+
548  struct function_traits<R (ClassType::*)(Args...)>
+
549  {
+
550  static const size_t arity = sizeof...(Args);
+
551 
+
552  typedef R result_type;
+
553 
+
554  template<size_t i>
+
555  using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
+
556  };
+
557 
+
558  template<typename R, typename... Args>
+
559  struct function_traits<std::function<R(Args...)>>
+
560  {
+
561  static const size_t arity = sizeof...(Args);
+
562 
+
563  typedef R result_type;
+
564 
+
565  template<size_t i>
+
566  using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
+
567  };
+
568  /// @endcond
+
569 
+
570  inline static std::string base64encode(const unsigned char* data, size_t size, const char* key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
+
571  {
+
572  std::string ret;
+
573  ret.resize((size + 2) / 3 * 4);
+
574  auto it = ret.begin();
+
575  while (size >= 3)
+
576  {
+
577  *it++ = key[(static_cast<unsigned char>(*data) & 0xFC) >> 2];
+
578  unsigned char h = (static_cast<unsigned char>(*data++) & 0x03) << 4;
+
579  *it++ = key[h | ((static_cast<unsigned char>(*data) & 0xF0) >> 4)];
+
580  h = (static_cast<unsigned char>(*data++) & 0x0F) << 2;
+
581  *it++ = key[h | ((static_cast<unsigned char>(*data) & 0xC0) >> 6)];
+
582  *it++ = key[static_cast<unsigned char>(*data++) & 0x3F];
+
583 
+
584  size -= 3;
+
585  }
+
586  if (size == 1)
+
587  {
+
588  *it++ = key[(static_cast<unsigned char>(*data) & 0xFC) >> 2];
+
589  unsigned char h = (static_cast<unsigned char>(*data++) & 0x03) << 4;
+
590  *it++ = key[h];
+
591  *it++ = '=';
+
592  *it++ = '=';
+
593  }
+
594  else if (size == 2)
+
595  {
+
596  *it++ = key[(static_cast<unsigned char>(*data) & 0xFC) >> 2];
+
597  unsigned char h = (static_cast<unsigned char>(*data++) & 0x03) << 4;
+
598  *it++ = key[h | ((static_cast<unsigned char>(*data) & 0xF0) >> 4)];
+
599  h = (static_cast<unsigned char>(*data++) & 0x0F) << 2;
+
600  *it++ = key[h];
+
601  *it++ = '=';
+
602  }
+
603  return ret;
+
604  }
+
605 
+
606  inline static std::string base64encode(std::string data, size_t size, const char* key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
+
607  {
+
608  return base64encode((const unsigned char*)data.c_str(), size, key);
+
609  }
+
610 
+
611  inline static std::string base64encode_urlsafe(const unsigned char* data, size_t size)
+
612  {
+
613  return base64encode(data, size, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
+
614  }
+
615 
+
616  inline static std::string base64encode_urlsafe(std::string data, size_t size)
+
617  {
+
618  return base64encode((const unsigned char*)data.c_str(), size, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
+
619  }
+
620 
+
621  inline static std::string base64decode(const char* data, size_t size)
+
622  {
+
623  // We accept both regular and url encoding here, as there does not seem to be any downside to that.
+
624  // If we want to distinguish that we should use +/ for non-url and -_ for url.
+
625 
+
626  // Mapping logic from characters to [0-63]
+
627  auto key = [](char c) -> unsigned char {
+
628  if ((c >= 'A') && (c <= 'Z')) return c - 'A';
+
629  if ((c >= 'a') && (c <= 'z')) return c - 'a' + 26;
+
630  if ((c >= '0') && (c <= '9')) return c - '0' + 52;
+
631  if ((c == '+') || (c == '-')) return 62;
+
632  if ((c == '/') || (c == '_')) return 63;
+
633  return 0;
+
634  };
+
635 
+
636  // Not padded
+
637  if (size % 4 == 2) // missing last 2 characters
+
638  size = (size / 4 * 3) + 1; // Not subtracting extra characters because they're truncated in int division
+
639  else if (size % 4 == 3) // missing last character
+
640  size = (size / 4 * 3) + 2; // Not subtracting extra characters because they're truncated in int division
+
641 
+
642  // Padded
+
643  else if (data[size - 2] == '=') // padded with '=='
+
644  size = (size / 4 * 3) - 2; // == padding means the last block only has 1 character instead of 3, hence the '-2'
+
645  else if (data[size - 1] == '=') // padded with '='
+
646  size = (size / 4 * 3) - 1; // = padding means the last block only has 2 character instead of 3, hence the '-1'
+
647 
+
648  // Padding not needed
+
649  else
+
650  size = size / 4 * 3;
+
651 
+
652  std::string ret;
+
653  ret.resize(size);
+
654  auto it = ret.begin();
+
655 
+
656  // These will be used to decode 1 character at a time
+
657  unsigned char odd; // char1 and char3
+
658  unsigned char even; // char2 and char4
+
659 
+
660  // Take 4 character blocks to turn into 3
+
661  while (size >= 3)
+
662  {
+
663  // dec_char1 = (char1 shifted 2 bits to the left) OR ((char2 AND 00110000) shifted 4 bits to the right))
+
664  odd = key(*data++);
+
665  even = key(*data++);
+
666  *it++ = (odd << 2) | ((even & 0x30) >> 4);
+
667  // dec_char2 = ((char2 AND 00001111) shifted 4 bits left) OR ((char3 AND 00111100) shifted 2 bits right))
+
668  odd = key(*data++);
+
669  *it++ = ((even & 0x0F) << 4) | ((odd & 0x3C) >> 2);
+
670  // dec_char3 = ((char3 AND 00000011) shifted 6 bits left) OR (char4)
+
671  even = key(*data++);
+
672  *it++ = ((odd & 0x03) << 6) | (even);
+
673 
+
674  size -= 3;
+
675  }
+
676  if (size == 2)
+
677  {
+
678  // d_char1 = (char1 shifted 2 bits to the left) OR ((char2 AND 00110000) shifted 4 bits to the right))
+
679  odd = key(*data++);
+
680  even = key(*data++);
+
681  *it++ = (odd << 2) | ((even & 0x30) >> 4);
+
682  // d_char2 = ((char2 AND 00001111) shifted 4 bits left) OR ((char3 AND 00111100) shifted 2 bits right))
+
683  odd = key(*data++);
+
684  *it++ = ((even & 0x0F) << 4) | ((odd & 0x3C) >> 2);
+
685  }
+
686  else if (size == 1)
+
687  {
+
688  // d_char1 = (char1 shifted 2 bits to the left) OR ((char2 AND 00110000) shifted 4 bits to the right))
+
689  odd = key(*data++);
+
690  even = key(*data++);
+
691  *it++ = (odd << 2) | ((even & 0x30) >> 4);
+
692  }
+
693  return ret;
+
694  }
+
695 
+
696  inline static std::string base64decode(const std::string& data, size_t size)
+
697  {
+
698  return base64decode(data.data(), size);
+
699  }
+
700 
+
701  inline static std::string base64decode(const std::string& data)
+
702  {
+
703  return base64decode(data.data(), data.length());
+
704  }
+
705 
+
706  inline static std::string normalize_path(const std::string& directoryPath)
+
707  {
+
708  std::string normalizedPath = directoryPath;
+
709  std::replace(normalizedPath.begin(), normalizedPath.end(), '\\', '/');
+
710  if (!normalizedPath.empty() && normalizedPath.back() != '/')
+
711  normalizedPath += '/';
+
712  return normalizedPath;
+
713  }
+
714 
+
715  inline static void sanitize_filename(std::string& data, char replacement = '_')
+
716  {
+
717  if (data.length() > 255)
+
718  data.resize(255);
+
719 
+
720  static const auto toUpper = [](char c) {
+
721  return ((c >= 'a') && (c <= 'z')) ? (c - ('a' - 'A')) : c;
+
722  };
+
723  // Check for special device names. The Windows behavior is really odd here, it will consider both AUX and AUX.txt
+
724  // a special device. Thus we search for the string (case-insensitive), and then check if the string ends or if
+
725  // is has a dangerous follow up character (.:\/)
+
726  auto sanitizeSpecialFile = [](std::string& source, unsigned ofs, const char* pattern, bool includeNumber, char replacement) {
+
727  unsigned i = ofs;
+
728  size_t len = source.length();
+
729  const char* p = pattern;
+
730  while (*p)
+
731  {
+
732  if (i >= len) return;
+
733  if (toUpper(source[i]) != *p) return;
+
734  ++i;
+
735  ++p;
+
736  }
+
737  if (includeNumber)
+
738  {
+
739  if ((i >= len) || (source[i] < '1') || (source[i] > '9')) return;
+
740  ++i;
+
741  }
+
742  if ((i >= len) || (source[i] == '.') || (source[i] == ':') || (source[i] == '/') || (source[i] == '\\'))
+
743  {
+
744  source.erase(ofs + 1, (i - ofs) - 1);
+
745  source[ofs] = replacement;
+
746  }
+
747  };
+
748  bool checkForSpecialEntries = true;
+
749  for (unsigned i = 0; i < data.length(); ++i)
+
750  {
+
751  // Recognize directory traversals and the special devices CON/PRN/AUX/NULL/COM[1-]/LPT[1-9]
+
752  if (checkForSpecialEntries)
+
753  {
+
754  checkForSpecialEntries = false;
+
755  switch (toUpper(data[i]))
+
756  {
+
757  case 'A':
+
758  sanitizeSpecialFile(data, i, "AUX", false, replacement);
+
759  break;
+
760  case 'C':
+
761  sanitizeSpecialFile(data, i, "CON", false, replacement);
+
762  sanitizeSpecialFile(data, i, "COM", true, replacement);
+
763  break;
+
764  case 'L':
+
765  sanitizeSpecialFile(data, i, "LPT", true, replacement);
+
766  break;
+
767  case 'N':
+
768  sanitizeSpecialFile(data, i, "NUL", false, replacement);
+
769  break;
+
770  case 'P':
+
771  sanitizeSpecialFile(data, i, "PRN", false, replacement);
+
772  break;
+
773  case '.':
+
774  sanitizeSpecialFile(data, i, "..", false, replacement);
+
775  break;
+
776  }
+
777  }
+
778 
+
779  // Sanitize individual characters
+
780  unsigned char c = data[i];
+
781  if ((c < ' ') || ((c >= 0x80) && (c <= 0x9F)) || (c == '?') || (c == '<') || (c == '>') || (c == ':') || (c == '*') || (c == '|') || (c == '\"'))
+
782  {
+
783  data[i] = replacement;
+
784  }
+
785  else if ((c == '/') || (c == '\\'))
+
786  {
+
787  if (CROW_UNLIKELY(i == 0)) //Prevent Unix Absolute Paths (Windows Absolute Paths are prevented with `(c == ':')`)
+
788  {
+
789  data[i] = replacement;
+
790  }
+
791  else
+
792  {
+
793  checkForSpecialEntries = true;
+
794  }
+
795  }
+
796  }
+
797  }
+
798 
+
799  inline static std::string random_alphanum(std::size_t size)
+
800  {
+
801  static const char alphabet[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
802  std::random_device dev;
+
803  std::mt19937 rng(dev());
+
804  std::uniform_int_distribution<std::mt19937::result_type> dist(0, sizeof(alphabet) - 2);
+
805  std::string out;
+
806  out.reserve(size);
+
807  for (std::size_t i = 0; i < size; i++)
+
808  out.push_back(alphabet[dist(rng)]);
+
809  return out;
+
810  }
+
811 
+
812  inline static std::string join_path(std::string path, const std::string& fname)
+
813  {
+
814 #if defined(CROW_CAN_USE_CPP17) && !defined(CROW_FILESYSTEM_IS_EXPERIMENTAL)
+
815  return (std::filesystem::path(path) / fname).string();
+
816 #else
+
817  if (!(path.back() == '/' || path.back() == '\\'))
+
818  path += '/';
+
819  path += fname;
+
820  return path;
+
821 #endif
+
822  }
+
823 
+
824  /**
+
825  * @brief Checks two string for equality.
+
826  * Always returns false if strings differ in size.
+
827  * Defaults to case-insensitive comparison.
+
828  */
+
829  inline static bool string_equals(const std::string& l, const std::string& r, bool case_sensitive = false)
+
830  {
+
831  if (l.length() != r.length())
+
832  return false;
+
833 
+
834  for (size_t i = 0; i < l.length(); i++)
+
835  {
+
836  if (case_sensitive)
+
837  {
+
838  if (l[i] != r[i])
+
839  return false;
+
840  }
+
841  else
+
842  {
+
843  if (std::toupper(l[i]) != std::toupper(r[i]))
+
844  return false;
+
845  }
+
846  }
+
847 
+
848  return true;
+
849  }
+
850 
+
851  template<typename T, typename U>
+
852  inline static T lexical_cast(const U& v)
+
853  {
+
854  std::stringstream stream;
+
855  T res;
+
856 
+
857  stream << v;
+
858  stream >> res;
+
859 
+
860  return res;
+
861  }
+
862 
+
863  template<typename T>
+
864  inline static T lexical_cast(const char* v, size_t count)
+
865  {
+
866  std::stringstream stream;
+
867  T res;
+
868 
+
869  stream.write(v, count);
+
870  stream >> res;
+
871 
+
872  return res;
+
873  }
+
874 
+
875 
+
876  /// Return a copy of the given string with its
+
877  /// leading and trailing whitespaces removed.
+
878  inline static std::string trim(const std::string& v)
+
879  {
+
880  if (v.empty())
+
881  return "";
+
882 
+
883  size_t begin = 0, end = v.length();
+
884 
+
885  size_t i;
+
886  for (i = 0; i < v.length(); i++)
+
887  {
+
888  if (!std::isspace(v[i]))
+
889  {
+
890  begin = i;
+
891  break;
+
892  }
+
893  }
+
894 
+
895  if (i == v.length())
+
896  return "";
+
897 
+
898  for (i = v.length(); i > 0; i--)
+
899  {
+
900  if (!std::isspace(v[i - 1]))
+
901  {
+
902  end = i;
+
903  break;
+
904  }
+
905  }
+
906 
+
907  return v.substr(begin, end - begin);
+
908  }
+
909  } // namespace utility
+
910 } // namespace crow
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/version_8h_source.html b/1.2/reference/version_8h_source.html new file mode 100644 index 000000000..75ff06ca2 --- /dev/null +++ b/1.2/reference/version_8h_source.html @@ -0,0 +1,124 @@ + + + + + + + + Crow: include/crow/version.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
version.h
+
+
+
1 #pragma once
+
2 
+
3 namespace crow
+
4 {
+
5  constexpr const char VERSION[] = "master";
+
6 }
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/reference/websocket_8h_source.html b/1.2/reference/websocket_8h_source.html new file mode 100644 index 000000000..0a8cf00a8 --- /dev/null +++ b/1.2/reference/websocket_8h_source.html @@ -0,0 +1,899 @@ + + + + + + + + Crow: include/crow/websocket.h Source File + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+
Crow +  1.1 +
+
A C++ microframework for the web
+
+ + + + + + +
+
+
+ + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
websocket.h
+
+
+
1 #pragma once
+
2 #include <array>
+
3 #include "crow/logging.h"
+
4 #include "crow/socket_adaptors.h"
+
5 #include "crow/http_request.h"
+
6 #include "crow/TinySHA1.hpp"
+
7 #include "crow/utility.h"
+
8 
+
9 namespace crow // NOTE: Already documented in "crow/app.h"
+
10 {
+
11 #ifdef CROW_USE_BOOST
+
12  namespace asio = boost::asio;
+
13  using error_code = boost::system::error_code;
+
14 #else
+
15  using error_code = asio::error_code;
+
16 #endif
+
17 
+
18  /**
+
19  * \namespace crow::websocket
+
20  * \brief Namespace that includes the \ref Connection class
+
21  * and \ref connection struct. Useful for WebSockets connection.
+
22  *
+
23  * Used specially in crow/websocket.h, crow/app.h and crow/routing.h
+
24  */
+
25  namespace websocket
+
26  {
+
27  enum class WebSocketReadState
+
28  {
+
29  MiniHeader,
+
30  Len16,
+
31  Len64,
+
32  Mask,
+
33  Payload,
+
34  };
+
35 
+
36  /// A base class for websocket connection.
+
37  struct connection
+
38  {
+
39  virtual void send_binary(std::string msg) = 0;
+
40  virtual void send_text(std::string msg) = 0;
+
41  virtual void send_ping(std::string msg) = 0;
+
42  virtual void send_pong(std::string msg) = 0;
+
43  virtual void close(std::string const& msg = "quit") = 0;
+
44  virtual std::string get_remote_ip() = 0;
+
45  virtual ~connection() = default;
+
46 
+
47  void userdata(void* u) { userdata_ = u; }
+
48  void* userdata() { return userdata_; }
+
49 
+
50  private:
+
51  void* userdata_;
+
52  };
+
53 
+
54  // Modified version of the illustration in RFC6455 Section-5.2
+
55  //
+
56  //
+
57  // 0 1 2 3 -byte
+
58  // 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 -bit
+
59  // +-+-+-+-+-------+-+-------------+-------------------------------+
+
60  // |F|R|R|R| opcode|M| Payload len | Extended payload length |
+
61  // |I|S|S|S| (4) |A| (7) | (16/64) |
+
62  // |N|V|V|V| |S| | (if payload len==126/127) |
+
63  // | |1|2|3| |K| | |
+
64  // +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
+
65  // | Extended payload length continued, if payload len == 127 |
+
66  // + - - - - - - - - - - - - - - - +-------------------------------+
+
67  // | |Masking-key, if MASK set to 1 |
+
68  // +-------------------------------+-------------------------------+
+
69  // | Masking-key (continued) | Payload Data |
+
70  // +-------------------------------- - - - - - - - - - - - - - - - +
+
71  // : Payload Data continued ... :
+
72  // + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+
73  // | Payload Data continued ... |
+
74  // +---------------------------------------------------------------+
+
75  //
+
76 
+
77  /// A websocket connection.
+
78 
+
79  template<typename Adaptor, typename Handler>
+
80  class Connection : public connection
+
81  {
+
82  public:
+
83  /// Constructor for a connection.
+
84 
+
85  ///
+
86  /// Requires a request with an "Upgrade: websocket" header.<br>
+
87  /// Automatically handles the handshake.
+
88  Connection(const crow::request& req, Adaptor&& adaptor, Handler* handler, uint64_t max_payload,
+
89  std::function<void(crow::websocket::connection&)> open_handler,
+
90  std::function<void(crow::websocket::connection&, const std::string&, bool)> message_handler,
+
91  std::function<void(crow::websocket::connection&, const std::string&)> close_handler,
+
92  std::function<void(crow::websocket::connection&, const std::string&)> error_handler,
+
93  std::function<bool(const crow::request&, void**)> accept_handler):
+
94  adaptor_(std::move(adaptor)),
+
95  handler_(handler),
+
96  max_payload_bytes_(max_payload),
+
97  open_handler_(std::move(open_handler)),
+
98  message_handler_(std::move(message_handler)),
+
99  close_handler_(std::move(close_handler)),
+
100  error_handler_(std::move(error_handler)),
+
101  accept_handler_(std::move(accept_handler))
+
102  {
+
103  if (!utility::string_equals(req.get_header_value("upgrade"), "websocket"))
+
104  {
+
105  adaptor_.close();
+
106  handler_->remove_websocket(this);
+
107  delete this;
+
108  return;
+
109  }
+
110 
+
111  if (accept_handler_)
+
112  {
+
113  void* ud = nullptr;
+
114  if (!accept_handler_(req, &ud))
+
115  {
+
116  adaptor_.close();
+
117  handler_->remove_websocket(this);
+
118  delete this;
+
119  return;
+
120  }
+
121  userdata(ud);
+
122  }
+
123 
+
124  // Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+
125  // Sec-WebSocket-Version: 13
+
126  std::string magic = req.get_header_value("Sec-WebSocket-Key") + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+
127  sha1::SHA1 s;
+
128  s.processBytes(magic.data(), magic.size());
+
129  uint8_t digest[20];
+
130  s.getDigestBytes(digest);
+
131 
+
132  start(crow::utility::base64encode((unsigned char*)digest, 20));
+
133  }
+
134 
+
135  ~Connection() noexcept override
+
136  {
+
137  // Do not modify anchor_ here since writing shared_ptr is not atomic.
+
138  auto watch = std::weak_ptr<void>{anchor_};
+
139 
+
140  // Wait until all unhandled asynchronous operations to join.
+
141  // As the deletion occurs inside 'check_destroy()', which already locks
+
142  // anchor, use count can be 1 on valid deletion context.
+
143  while (watch.use_count() > 2) // 1 for 'check_destroy() routine', 1 for 'this->anchor_'
+
144  {
+
145  std::this_thread::yield();
+
146  }
+
147  }
+
148 
+
149  template<typename Callable>
+ +
151  {
+
152  Callable callable;
+
153  std::weak_ptr<void> watch;
+
154 
+
155  void operator()()
+
156  {
+
157  if (auto anchor = watch.lock())
+
158  {
+
159  std::move(callable)();
+
160  }
+
161  }
+
162  };
+
163 
+
164  /// Send data through the socket.
+
165  template<typename CompletionHandler>
+
166  void dispatch(CompletionHandler&& handler)
+
167  {
+
168  asio::dispatch(adaptor_.get_io_service(),
+
169  WeakWrappedMessage<typename std::decay<CompletionHandler>::type>{
+
170  std::forward<CompletionHandler>(handler), anchor_});
+
171  }
+
172 
+
173  /// Send data through the socket and return immediately.
+
174  template<typename CompletionHandler>
+
175  void post(CompletionHandler&& handler)
+
176  {
+
177  asio::post(adaptor_.get_io_service(),
+
178  WeakWrappedMessage<typename std::decay<CompletionHandler>::type>{
+
179  std::forward<CompletionHandler>(handler), anchor_});
+
180  }
+
181 
+
182  /// Send a "Ping" message.
+
183 
+
184  ///
+
185  /// Usually invoked to check if the other point is still online.
+
186  void send_ping(std::string msg) override
+
187  {
+
188  send_data(0x9, std::move(msg));
+
189  }
+
190 
+
191  /// Send a "Pong" message.
+
192 
+
193  ///
+
194  /// Usually automatically invoked as a response to a "Ping" message.
+
195  void send_pong(std::string msg) override
+
196  {
+
197  send_data(0xA, std::move(msg));
+
198  }
+
199 
+
200  /// Send a binary encoded message.
+
201  void send_binary(std::string msg) override
+
202  {
+
203  send_data(0x2, std::move(msg));
+
204  }
+
205 
+
206  /// Send a plaintext message.
+
207  void send_text(std::string msg) override
+
208  {
+
209  send_data(0x1, std::move(msg));
+
210  }
+
211 
+
212  /// Send a close signal.
+
213 
+
214  ///
+
215  /// Sets a flag to destroy the object once the message is sent.
+
216  void close(std::string const& msg) override
+
217  {
+
218  dispatch([this, msg]() mutable {
+
219  has_sent_close_ = true;
+
220  if (has_recv_close_ && !is_close_handler_called_)
+
221  {
+
222  is_close_handler_called_ = true;
+
223  if (close_handler_)
+
224  close_handler_(*this, msg);
+
225  }
+
226  auto header = build_header(0x8, msg.size());
+
227  write_buffers_.emplace_back(std::move(header));
+
228  write_buffers_.emplace_back(msg);
+
229  do_write();
+
230  });
+
231  }
+
232 
+
233  std::string get_remote_ip() override
+
234  {
+
235  return adaptor_.remote_endpoint().address().to_string();
+
236  }
+
237 
+
238  void set_max_payload_size(uint64_t payload)
+
239  {
+
240  max_payload_bytes_ = payload;
+
241  }
+
242 
+
243  protected:
+
244  /// Generate the websocket headers using an opcode and the message size (in bytes).
+
245  std::string build_header(int opcode, size_t size)
+
246  {
+
247  char buf[2 + 8] = "\x80\x00";
+
248  buf[0] += opcode;
+
249  if (size < 126)
+
250  {
+
251  buf[1] += static_cast<char>(size);
+
252  return {buf, buf + 2};
+
253  }
+
254  else if (size < 0x10000)
+
255  {
+
256  buf[1] += 126;
+
257  *(uint16_t*)(buf + 2) = htons(static_cast<uint16_t>(size));
+
258  return {buf, buf + 4};
+
259  }
+
260  else
+
261  {
+
262  buf[1] += 127;
+
263  *reinterpret_cast<uint64_t*>(buf + 2) = ((1 == htonl(1)) ? static_cast<uint64_t>(size) : (static_cast<uint64_t>(htonl((size)&0xFFFFFFFF)) << 32) | htonl(static_cast<uint64_t>(size) >> 32));
+
264  return {buf, buf + 10};
+
265  }
+
266  }
+
267 
+
268  /// Send the HTTP upgrade response.
+
269 
+
270  ///
+
271  /// Finishes the handshake process, then starts reading messages from the socket.
+
272  void start(std::string&& hello)
+
273  {
+
274  static const std::string header =
+
275  "HTTP/1.1 101 Switching Protocols\r\n"
+
276  "Upgrade: websocket\r\n"
+
277  "Connection: Upgrade\r\n"
+
278  "Sec-WebSocket-Accept: ";
+
279  write_buffers_.emplace_back(header);
+
280  write_buffers_.emplace_back(std::move(hello));
+
281  write_buffers_.emplace_back(crlf);
+
282  write_buffers_.emplace_back(crlf);
+
283  do_write();
+
284  if (open_handler_)
+
285  open_handler_(*this);
+
286  do_read();
+
287  }
+
288 
+
289  /// Read a websocket message.
+
290 
+
291  ///
+
292  /// Involves:<br>
+
293  /// Handling headers (opcodes, size).<br>
+
294  /// Unmasking the payload.<br>
+
295  /// Reading the actual payload.<br>
+
296  void do_read()
+
297  {
+
298  if (has_sent_close_ && has_recv_close_)
+
299  {
+
300  close_connection_ = true;
+
301  adaptor_.shutdown_readwrite();
+
302  adaptor_.close();
+
303  check_destroy();
+
304  return;
+
305  }
+
306 
+
307  is_reading = true;
+
308  switch (state_)
+
309  {
+
310  case WebSocketReadState::MiniHeader:
+
311  {
+
312  mini_header_ = 0;
+
313  //asio::async_read(adaptor_.socket(), asio::buffer(&mini_header_, 1),
+
314  adaptor_.socket().async_read_some(
+
315  asio::buffer(&mini_header_, 2),
+
316  [this](const error_code& ec, std::size_t
+
317 #ifdef CROW_ENABLE_DEBUG
+
318  bytes_transferred
+
319 #endif
+
320  )
+
321 
+
322  {
+
323  is_reading = false;
+
324  mini_header_ = ntohs(mini_header_);
+
325 #ifdef CROW_ENABLE_DEBUG
+
326 
+
327  if (!ec && bytes_transferred != 2)
+
328  {
+
329  throw std::runtime_error("WebSocket:MiniHeader:async_read fail:asio bug?");
+
330  }
+
331 #endif
+
332 
+
333  if (!ec)
+
334  {
+
335  if ((mini_header_ & 0x80) == 0x80)
+
336  has_mask_ = true;
+
337  else //if the websocket specification is enforced and the message isn't masked, terminate the connection
+
338  {
+
339 #ifndef CROW_ENFORCE_WS_SPEC
+
340  has_mask_ = false;
+
341 #else
+
342  close_connection_ = true;
+
343  adaptor_.shutdown_readwrite();
+
344  adaptor_.close();
+
345  if (error_handler_)
+
346  error_handler_(*this, "Client connection not masked.");
+
347  check_destroy();
+
348 #endif
+
349  }
+
350 
+
351  if ((mini_header_ & 0x7f) == 127)
+
352  {
+
353  state_ = WebSocketReadState::Len64;
+
354  }
+
355  else if ((mini_header_ & 0x7f) == 126)
+
356  {
+
357  state_ = WebSocketReadState::Len16;
+
358  }
+
359  else
+
360  {
+
361  remaining_length_ = mini_header_ & 0x7f;
+
362  state_ = WebSocketReadState::Mask;
+
363  }
+
364  do_read();
+
365  }
+
366  else
+
367  {
+
368  close_connection_ = true;
+
369  adaptor_.shutdown_readwrite();
+
370  adaptor_.close();
+
371  if (error_handler_)
+
372  error_handler_(*this, ec.message());
+
373  check_destroy();
+
374  }
+
375  });
+
376  }
+
377  break;
+
378  case WebSocketReadState::Len16:
+
379  {
+
380  remaining_length_ = 0;
+
381  remaining_length16_ = 0;
+
382  asio::async_read(
+
383  adaptor_.socket(), asio::buffer(&remaining_length16_, 2),
+
384  [this](const error_code& ec, std::size_t
+
385 #ifdef CROW_ENABLE_DEBUG
+
386  bytes_transferred
+
387 #endif
+
388  ) {
+
389  is_reading = false;
+
390  remaining_length16_ = ntohs(remaining_length16_);
+
391  remaining_length_ = remaining_length16_;
+
392 #ifdef CROW_ENABLE_DEBUG
+
393  if (!ec && bytes_transferred != 2)
+
394  {
+
395  throw std::runtime_error("WebSocket:Len16:async_read fail:asio bug?");
+
396  }
+
397 #endif
+
398 
+
399  if (!ec)
+
400  {
+
401  state_ = WebSocketReadState::Mask;
+
402  do_read();
+
403  }
+
404  else
+
405  {
+
406  close_connection_ = true;
+
407  adaptor_.shutdown_readwrite();
+
408  adaptor_.close();
+
409  if (error_handler_)
+
410  error_handler_(*this, ec.message());
+
411  check_destroy();
+
412  }
+
413  });
+
414  }
+
415  break;
+
416  case WebSocketReadState::Len64:
+
417  {
+
418  asio::async_read(
+
419  adaptor_.socket(), asio::buffer(&remaining_length_, 8),
+
420  [this](const error_code& ec, std::size_t
+
421 #ifdef CROW_ENABLE_DEBUG
+
422  bytes_transferred
+
423 #endif
+
424  ) {
+
425  is_reading = false;
+
426  remaining_length_ = ((1 == ntohl(1)) ? (remaining_length_) : (static_cast<uint64_t>(ntohl((remaining_length_)&0xFFFFFFFF)) << 32) | ntohl((remaining_length_) >> 32));
+
427 #ifdef CROW_ENABLE_DEBUG
+
428  if (!ec && bytes_transferred != 8)
+
429  {
+
430  throw std::runtime_error("WebSocket:Len16:async_read fail:asio bug?");
+
431  }
+
432 #endif
+
433 
+
434  if (!ec)
+
435  {
+
436  state_ = WebSocketReadState::Mask;
+
437  do_read();
+
438  }
+
439  else
+
440  {
+
441  close_connection_ = true;
+
442  adaptor_.shutdown_readwrite();
+
443  adaptor_.close();
+
444  if (error_handler_)
+
445  error_handler_(*this, ec.message());
+
446  check_destroy();
+
447  }
+
448  });
+
449  }
+
450  break;
+
451  case WebSocketReadState::Mask:
+
452  if (remaining_length_ > max_payload_bytes_)
+
453  {
+
454  close_connection_ = true;
+
455  adaptor_.close();
+
456  if (error_handler_)
+
457  error_handler_(*this, "Message length exceeds maximum payload.");
+
458  check_destroy();
+
459  }
+
460  else if (has_mask_)
+
461  {
+
462  asio::async_read(
+
463  adaptor_.socket(), asio::buffer((char*)&mask_, 4),
+
464  [this](const error_code& ec, std::size_t
+
465 #ifdef CROW_ENABLE_DEBUG
+
466  bytes_transferred
+
467 #endif
+
468  ) {
+
469  is_reading = false;
+
470 #ifdef CROW_ENABLE_DEBUG
+
471  if (!ec && bytes_transferred != 4)
+
472  {
+
473  throw std::runtime_error("WebSocket:Mask:async_read fail:asio bug?");
+
474  }
+
475 #endif
+
476 
+
477  if (!ec)
+
478  {
+
479  state_ = WebSocketReadState::Payload;
+
480  do_read();
+
481  }
+
482  else
+
483  {
+
484  close_connection_ = true;
+
485  if (error_handler_)
+
486  error_handler_(*this, ec.message());
+
487  adaptor_.shutdown_readwrite();
+
488  adaptor_.close();
+
489  check_destroy();
+
490  }
+
491  });
+
492  }
+
493  else
+
494  {
+
495  state_ = WebSocketReadState::Payload;
+
496  do_read();
+
497  }
+
498  break;
+
499  case WebSocketReadState::Payload:
+
500  {
+
501  auto to_read = static_cast<std::uint64_t>(buffer_.size());
+
502  if (remaining_length_ < to_read)
+
503  to_read = remaining_length_;
+
504  adaptor_.socket().async_read_some(
+
505  asio::buffer(buffer_, static_cast<std::size_t>(to_read)),
+
506  [this](const error_code& ec, std::size_t bytes_transferred) {
+
507  is_reading = false;
+
508 
+
509  if (!ec)
+
510  {
+
511  fragment_.insert(fragment_.end(), buffer_.begin(), buffer_.begin() + bytes_transferred);
+
512  remaining_length_ -= bytes_transferred;
+
513  if (remaining_length_ == 0)
+
514  {
+
515  if (handle_fragment())
+
516  {
+
517  state_ = WebSocketReadState::MiniHeader;
+
518  do_read();
+
519  }
+
520  }
+
521  else
+
522  do_read();
+
523  }
+
524  else
+
525  {
+
526  close_connection_ = true;
+
527  if (error_handler_)
+
528  error_handler_(*this, ec.message());
+
529  adaptor_.shutdown_readwrite();
+
530  adaptor_.close();
+
531  check_destroy();
+
532  }
+
533  });
+
534  }
+
535  break;
+
536  }
+
537  }
+
538 
+
539  /// Check if the FIN bit is set.
+
540  bool is_FIN()
+
541  {
+
542  return mini_header_ & 0x8000;
+
543  }
+
544 
+
545  /// Extract the opcode from the header.
+
546  int opcode()
+
547  {
+
548  return (mini_header_ & 0x0f00) >> 8;
+
549  }
+
550 
+
551  /// Process the payload fragment.
+
552 
+
553  ///
+
554  /// Unmasks the fragment, checks the opcode, merges fragments into 1 message body, and calls the appropriate handler.
+ +
556  {
+
557  if (has_mask_)
+
558  {
+
559  for (decltype(fragment_.length()) i = 0; i < fragment_.length(); i++)
+
560  {
+
561  fragment_[i] ^= ((char*)&mask_)[i % 4];
+
562  }
+
563  }
+
564  switch (opcode())
+
565  {
+
566  case 0: // Continuation
+
567  {
+
568  message_ += fragment_;
+
569  if (is_FIN())
+
570  {
+
571  if (message_handler_)
+
572  message_handler_(*this, message_, is_binary_);
+
573  message_.clear();
+
574  }
+
575  }
+
576  break;
+
577  case 1: // Text
+
578  {
+
579  is_binary_ = false;
+
580  message_ += fragment_;
+
581  if (is_FIN())
+
582  {
+
583  if (message_handler_)
+
584  message_handler_(*this, message_, is_binary_);
+
585  message_.clear();
+
586  }
+
587  }
+
588  break;
+
589  case 2: // Binary
+
590  {
+
591  is_binary_ = true;
+
592  message_ += fragment_;
+
593  if (is_FIN())
+
594  {
+
595  if (message_handler_)
+
596  message_handler_(*this, message_, is_binary_);
+
597  message_.clear();
+
598  }
+
599  }
+
600  break;
+
601  case 0x8: // Close
+
602  {
+
603  has_recv_close_ = true;
+
604  if (!has_sent_close_)
+
605  {
+
606  close(fragment_);
+
607  }
+
608  else
+
609  {
+
610  adaptor_.shutdown_readwrite();
+
611  adaptor_.close();
+
612  close_connection_ = true;
+
613  if (!is_close_handler_called_)
+
614  {
+
615  if (close_handler_)
+
616  close_handler_(*this, fragment_);
+
617  is_close_handler_called_ = true;
+
618  }
+
619  check_destroy();
+
620  return false;
+
621  }
+
622  }
+
623  break;
+
624  case 0x9: // Ping
+
625  {
+
626  send_pong(fragment_);
+
627  }
+
628  break;
+
629  case 0xA: // Pong
+
630  {
+
631  pong_received_ = true;
+
632  }
+
633  break;
+
634  }
+
635 
+
636  fragment_.clear();
+
637  return true;
+
638  }
+
639 
+
640  /// Send the buffers' data through the socket.
+
641 
+
642  ///
+
643  /// Also destroys the object if the Close flag is set.
+
644  void do_write()
+
645  {
+
646  if (sending_buffers_.empty())
+
647  {
+
648  sending_buffers_.swap(write_buffers_);
+
649  std::vector<asio::const_buffer> buffers;
+
650  buffers.reserve(sending_buffers_.size());
+
651  for (auto& s : sending_buffers_)
+
652  {
+
653  buffers.emplace_back(asio::buffer(s));
+
654  }
+
655  auto watch = std::weak_ptr<void>{anchor_};
+
656  asio::async_write(
+
657  adaptor_.socket(), buffers,
+
658  [&, watch](const error_code& ec, std::size_t /*bytes_transferred*/) {
+
659  if (!ec && !close_connection_)
+
660  {
+
661  sending_buffers_.clear();
+
662  if (!write_buffers_.empty())
+
663  do_write();
+
664  if (has_sent_close_)
+
665  close_connection_ = true;
+
666  }
+
667  else
+
668  {
+
669  auto anchor = watch.lock();
+
670  if (anchor == nullptr) { return; }
+
671 
+
672  sending_buffers_.clear();
+
673  close_connection_ = true;
+
674  check_destroy();
+
675  }
+
676  });
+
677  }
+
678  }
+
679 
+
680  /// Destroy the Connection.
+ +
682  {
+
683  //if (has_sent_close_ && has_recv_close_)
+
684  if (!is_close_handler_called_)
+
685  if (close_handler_)
+
686  close_handler_(*this, "uncleanly");
+
687  handler_->remove_websocket(this);
+
688  if (sending_buffers_.empty() && !is_reading)
+
689  delete this;
+
690  }
+
691 
+
692 
+ +
694  {
+
695  std::string payload;
+
696  Connection* self;
+
697  int opcode;
+
698 
+
699  void operator()()
+
700  {
+
701  self->send_data_impl(this);
+
702  }
+
703  };
+
704 
+
705  void send_data_impl(SendMessageType* s)
+
706  {
+
707  auto header = build_header(s->opcode, s->payload.size());
+
708  write_buffers_.emplace_back(std::move(header));
+
709  write_buffers_.emplace_back(std::move(s->payload));
+
710  do_write();
+
711  }
+
712 
+
713  void send_data(int opcode, std::string&& msg)
+
714  {
+
715  SendMessageType event_arg{
+
716  std::move(msg),
+
717  this,
+
718  opcode};
+
719 
+
720  post(std::move(event_arg));
+
721  }
+
722 
+
723  private:
+
724  Adaptor adaptor_;
+
725  Handler* handler_;
+
726 
+
727  std::vector<std::string> sending_buffers_;
+
728  std::vector<std::string> write_buffers_;
+
729 
+
730  std::array<char, 4096> buffer_;
+
731  bool is_binary_;
+
732  std::string message_;
+
733  std::string fragment_;
+
734  WebSocketReadState state_{WebSocketReadState::MiniHeader};
+
735  uint16_t remaining_length16_{0};
+
736  uint64_t remaining_length_{0};
+
737  uint64_t max_payload_bytes_{UINT64_MAX};
+
738  bool close_connection_{false};
+
739  bool is_reading{false};
+
740  bool has_mask_{false};
+
741  uint32_t mask_;
+
742  uint16_t mini_header_;
+
743  bool has_sent_close_{false};
+
744  bool has_recv_close_{false};
+
745  bool error_occurred_{false};
+
746  bool pong_received_{false};
+
747  bool is_close_handler_called_{false};
+
748 
+
749  std::shared_ptr<void> anchor_ = std::make_shared<int>(); // Value is just for placeholding
+
750 
+
751  std::function<void(crow::websocket::connection&)> open_handler_;
+
752  std::function<void(crow::websocket::connection&, const std::string&, bool)> message_handler_;
+
753  std::function<void(crow::websocket::connection&, const std::string&)> close_handler_;
+
754  std::function<void(crow::websocket::connection&, const std::string&)> error_handler_;
+
755  std::function<bool(const crow::request&, void**)> accept_handler_;
+
756  };
+
757  } // namespace websocket
+
758 } // namespace crow
+
TinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based on the implementation in ...
+
A websocket connection.
Definition: websocket.h:81
+
void dispatch(CompletionHandler &&handler)
Send data through the socket.
Definition: websocket.h:166
+
void do_read()
Read a websocket message.
Definition: websocket.h:296
+
void send_pong(std::string msg) override
Send a "Pong" message.
Definition: websocket.h:195
+
bool handle_fragment()
Process the payload fragment.
Definition: websocket.h:555
+
std::string build_header(int opcode, size_t size)
Generate the websocket headers using an opcode and the message size (in bytes).
Definition: websocket.h:245
+
void send_text(std::string msg) override
Send a plaintext message.
Definition: websocket.h:207
+
void close(std::string const &msg) override
Send a close signal.
Definition: websocket.h:216
+
int opcode()
Extract the opcode from the header.
Definition: websocket.h:546
+
void do_write()
Send the buffers' data through the socket.
Definition: websocket.h:644
+
void check_destroy()
Destroy the Connection.
Definition: websocket.h:681
+
void start(std::string &&hello)
Send the HTTP upgrade response.
Definition: websocket.h:272
+
bool is_FIN()
Check if the FIN bit is set.
Definition: websocket.h:540
+
void send_ping(std::string msg) override
Send a "Ping" message.
Definition: websocket.h:186
+
void send_binary(std::string msg) override
Send a binary encoded message.
Definition: websocket.h:201
+
Connection(const crow::request &req, Adaptor &&adaptor, Handler *handler, uint64_t max_payload, std::function< void(crow::websocket::connection &)> open_handler, std::function< void(crow::websocket::connection &, const std::string &, bool)> message_handler, std::function< void(crow::websocket::connection &, const std::string &)> close_handler, std::function< void(crow::websocket::connection &, const std::string &)> error_handler, std::function< bool(const crow::request &, void **)> accept_handler)
Constructor for a connection.
Definition: websocket.h:88
+
void post(CompletionHandler &&handler)
Send data through the socket and return immediately.
Definition: websocket.h:175
+
A tiny SHA1 algorithm implementation used internally in the Crow server (specifically in crow/websock...
Definition: TinySHA1.hpp:48
+
The main namespace of the library. In this namespace is defined the most important classes and functi...
+
An HTTP request.
Definition: http_request.h:36
+ + +
A base class for websocket connection.
Definition: websocket.h:38
+
+
+ + + + + \ No newline at end of file diff --git a/1.2/search/search_index.json b/1.2/search/search_index.json new file mode 100644 index 000000000..1a09ba15e --- /dev/null +++ b/1.2/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"getting_started/a_simple_webpage/","title":"A Simple Webpage","text":"

Hello World is a good start, but what if you want something a bit more fancy.. Something like an HTML document saying \"Hello World\". If that's what you want, follow along:

"},{"location":"getting_started/a_simple_webpage/#basic-webpage","title":"Basic Webpage","text":"

Let's start our webpage with.. well.. a webpage. But before we create a webpage we need to place it somewhere Crow recognizes, for now this directory is going to be called templates, but we can change it later.

Once our templates folder is created, we can create our HTML document inside it, let's call it fancypage.html.

After that we can just place something simple inside it like: templates/fancypage.html

<!DOCTYPE html>\n<html>\n  <body>\n  <p>Hello World!</p>\n  </body>\n</html>\n
Now that we have our HTML page ready, let's take our Hello World example from earlier:
#include \"crow.h\"\n//#include \"crow_all.h\"\n\nint main()\n{\n    crow::SimpleApp app; //define your crow application\n\n    //define your endpoint at the root directory\n    CROW_ROUTE(app, \"/\")([](){\n        return \"Hello world\";\n    });\n\n    //set the port, set the app to run on multiple threads, and run the app\n    app.port(18080).multithreaded().run();\n}\n

And now let's modify it so that it returns our cool page: /main.cpp

#include \"crow.h\"\n//#include \"crow_all.h\"\n\nint main()\n{\n    crow::SimpleApp app;\n\n    //define your endpoint at the root directory\n    CROW_ROUTE(app, \"/\")([](){\n        auto page = crow::mustache::load_text(\"fancypage.html\");\n        return page;\n    });\n\n    app.port(18080).multithreaded().run();\n}\n

Your project should look something something like:

./\n |-templates/\n |          |-fancypage.html\n |\n |-main.cpp\n |-crow_all.h\n
or
./\n |-templates/\n |          |-fancypage.html\n |\n |-crow/\n |     |-include/...\n |     |-crow.h\n |-main.cpp\n

Once the code is done compiling, if we call http://localhost:18080/ we get our Hello World in an HTML document rather than just plain text.

Note

Compilation instructions are available for Linux, MacOS, and Windows

"},{"location":"getting_started/a_simple_webpage/#template-webpage-with-a-variable","title":"Template Webpage with a variable","text":"

But we can make things even more exciting, we can greet a user by their name instead!!

Let's start with our webpage, and modify it with a little bit of mustache syntax: templates/fancypage.html

<!DOCTYPE html>\n<html>\n  <body>\n  <p>Hello {{person}}!</p> <!--(1)-->\n  </body>\n</html>\n

  1. {{}} in mustache define a simple variable

Now let's modify our C++ code to use the variable we just added to our webpage (or template): /main.cpp

#include \"crow.h\"\n//#include \"crow_all.h\"\n\nint main()\n{\n    crow::SimpleApp app;\n\n    //define your endpoint at the root directory\n    CROW_ROUTE(app, \"/<string>\")([](std::string name){ // (1)\n        auto page = crow::mustache::load(\"fancypage.html\"); // (2)\n        crow::mustache::context ctx ({{\"person\", name}}); // (3)\n        return page.render(ctx); //(4)\n    });\n\n    app.port(18080).multithreaded().run();\n}\n

  1. We are adding a string variable to the URL and a counterpart (std::string name) to our route - this can be anything the user wants.
  2. We are using load() instead of load_text() since we have an actual variable now.
  3. We are creating a new context containing the person variable from our template and the name we got from the URL.
  4. We are using render(ctx) to apply our context to the template.

Now (after compiling the code and running the executable a second time) calling http://localhost:18080/Bob should return a webpage containing \"Hello Bob!\". We did it!

For more details on templates and HTML pages in Crow please go here

"},{"location":"getting_started/your_first_application/","title":"Your First Application","text":"

This page shows how you can get started with a simple hello world application.

"},{"location":"getting_started/your_first_application/#1-include","title":"1. Include","text":"

Starting with an empty main.cpp file, first add #include \"crow.h\" or #include \"crow_all.h\" if you're using the single header file.

Note

If you are using version v0.3, then you have to put #define CROW_MAIN at the top of one and only one source file.

"},{"location":"getting_started/your_first_application/#2-app-declaration","title":"2. App declaration","text":"

Next Create a main() and declare a crow::SimpleApp inside, your code should look like this

int main()\n{\n    crow::SimpleApp app;\n}\n
The App (or SimpleApp) class organizes all the different parts of Crow and provides the developer (you) a simple interface to interact with these parts. For more information, please go here.

"},{"location":"getting_started/your_first_application/#3-adding-routes","title":"3. Adding routes","text":"

Once you have your app, the next step is to add routes (or endpoints). You can do so with the CROW_ROUTE macro.

CROW_ROUTE(app, \"/\")([](){\n    return \"Hello world\";\n});\n
For more details on routes, please go here.

"},{"location":"getting_started/your_first_application/#4-running-the-app","title":"4. Running the app","text":"

Once you're happy with how you defined all your routes, you're going to want to instruct Crow to run your app. This is done using the run() method.

app.port(18080).multithreaded().run();\n
Please note that the port() and multithreaded() methods aren't needed, though not using port() will cause the default port (80) to be used.

"},{"location":"getting_started/your_first_application/#putting-it-all-together","title":"Putting it all together","text":"

Once you've followed all the steps above, your code should look similar to this

main.cpp
#include \"crow.h\"\n//#include \"crow_all.h\"\n\nint main()\n{\n    crow::SimpleApp app; //define your crow application\n\n    //define your endpoint at the root directory\n    CROW_ROUTE(app, \"/\")([](){\n        return \"Hello world\";\n    });\n\n    //set the port, set the app to run on multiple threads, and run the app\n    app.port(18080).multithreaded().run();\n}\n

You then need to compile your code on your Linux, MacOS, or Windows machine

After building your .cpp file and running the resulting executable, you should be able to access your endpoint at http://localhost:18080. Opening this URL in your browser will show a white screen with \"Hello world\" typed on it.

"},{"location":"getting_started/setup/linux/","title":"Linux","text":"

Here's how you can install Crow on your favorite GNU/Linux distro.

"},{"location":"getting_started/setup/linux/#getting-crow","title":"Getting Crow","text":""},{"location":"getting_started/setup/linux/#requirements","title":"Requirements","text":"
  • C++ compiler with at least C++11 support.
  • Asio development headers (1.10.9 or later).
  • (optional) ZLib for HTTP Compression.
  • (optional) OpenSSL for HTTPS support.
  • (optional) CMake for building tests, examples, and/or installing Crow.
  • (optional) Python3 to build tests and/or examples.

Note

Crow's CI uses g++-9.4 and clang-10.0 running on AMD64 (x86_64) and ARM64v8 architectures.

"},{"location":"getting_started/setup/linux/#using-a-package-manager","title":"Using a package Manager","text":"

You can install Crow on GNU/Linux as a pre-made package

Debian/Ubuntu

Simply download Crow's .deb file from the release section and Install it.

Arch

Crow is available for Arch based distros through the AUR package crow.

"},{"location":"getting_started/setup/linux/#release-package","title":"Release package","text":"

Crow provides an archive containing the framework and CMake files, just copy the include folder to /usr/local/include and lib folder to /usr/local/lib. You can also download the crow_all.h file and simply include that into your project.

"},{"location":"getting_started/setup/linux/#installing-from-source","title":"Installing from source","text":""},{"location":"getting_started/setup/linux/#using-cmake","title":"Using CMake","text":"
  1. Download Crow's source code (Either through Github's UI or by using git clone https://github.com/CrowCpp/Crow.git).
  2. Run mkdir build inside of crow's source directory.
  3. Navigate to the new \"build\" directory and run the following: cmake .. -DCROW_BUILD_EXAMPLES=OFF -DCROW_BUILD_TESTS=OFF
  4. Run make install.

Note

You can ignore -DCROW_BUILD_EXAMPLES=OFF -DCROW_BUILD_TESTS=OFF if you want to build the Examples and Unit Tests.

Note

While building you can set the CROW_FEATURES variable (as a ; separated list). You can use an argument such as -DCROW_FEATURES=\"ssl;compression\".

Note

You can uninstall Crow at a later time using make uninstall.

"},{"location":"getting_started/setup/linux/#manually","title":"Manually","text":"

Crow can be installed manually on your Linux computer.

"},{"location":"getting_started/setup/linux/#multiple-header-files","title":"Multiple header files","text":"Project Only

Copy Crow's include directory to your project's include directory.

System wide

Copy Crow's include directory to the /usr/local/include directory.

"},{"location":"getting_started/setup/linux/#single-header-crow_allh","title":"Single header (crow_all.h)","text":"

Warning

crow_all.h is recommended only for small, possibly single source file projects, and ideally should not be installed on your system.

navigate to the scripts directory and run ./merge_all.py ../include crow_all.h. This will generate a crow_all.h file that you can use in your projects.

Note

You can also include or exclude middlewares from your crow_all.h by using -i or -e followed by the middleware header file names separated by a comma (e.g. merge_all.py ../include crow_all.h -e cookie_parser to exclude the cookie parser middleware).

"},{"location":"getting_started/setup/linux/#compiling-your-project","title":"Compiling your project","text":""},{"location":"getting_started/setup/linux/#using-cmake_1","title":"Using CMake","text":"

In order to get your CMake project to work with Crow, all you need are the following lines in your CMakeLists.txt:

find_package(Crow)\ntarget_link_libraries(your_project PUBLIC Crow::Crow)\n
From there CMake should handle compiling and linking your project.

Note

For optional features like HTTP Compression or HTTPS you can set the CROW_FEATURES variable using lines such as set(CROW_FEATURES \"ssl;compression\"), set(CROW_FEATURES ssl compression), or set(CROW_FEATURES ssl).

"},{"location":"getting_started/setup/linux/#directly-using-a-compiler","title":"Directly using a compiler","text":"

All you need to do is run the following command:

g++ main.cpp -lpthread\n
You can use arguments like -DCROW_ENABLE_DEBUG, -DCROW_ENABLE_COMPRESSION -lz for HTTP Compression, or -DCROW_ENABLE_SSL -lssl for HTTPS support, or even replace g++ with clang++.

"},{"location":"getting_started/setup/macos/","title":"MacOS","text":"

Here's how you can install Crow on your Mac.

"},{"location":"getting_started/setup/macos/#getting-crow","title":"Getting Crow","text":""},{"location":"getting_started/setup/macos/#from-a-release","title":"From a release","text":""},{"location":"getting_started/setup/macos/#archive","title":"Archive","text":"

Crow provides an archive containing the framework and CMake files, You will only need the include folder inside that archive.

"},{"location":"getting_started/setup/macos/#single-header-file","title":"Single header file","text":"

You can also download the crow_all.h file which replaces the include folder.

"},{"location":"getting_started/setup/macos/#from-source","title":"From Source","text":"

To get Crow from source, you only need to download the repository (as a .zip or through git clone https://github.com/CrowCpp/Crow.git).

"},{"location":"getting_started/setup/macos/#include-folder","title":"include folder","text":"

Once you've downloaded Crow's source code, you only need to take the include folder.

"},{"location":"getting_started/setup/macos/#single-header-file_1","title":"Single header file","text":"

You can generate your own single header file by navigating to the scripts folder with your terminal and running the following command:

python3 merge_all.py ../include crow_all.h\n
This will generate a crow_all.h file which you can use in the following steps

Warning

crow_all.h is recommended only for small, possibly single source file projects. For larger projects, it is advised to use the multi-header version.

"},{"location":"getting_started/setup/macos/#setting-up-your-crow-project","title":"Setting up your Crow project","text":""},{"location":"getting_started/setup/macos/#using-xcode","title":"Using XCode","text":"
  1. Download and install Homebrew.
  2. Run brew install asio in your terminal.
  3. Create a new XCode project (macOS -> Command Line Tool).
  4. Change the following project settings:

    Multiple Headers
    1. Add header search paths for crow's include folder and asio's folder (/usr/local/include, /usr/local/Cellar/asio/include, and where you placed Crow's include folder)
    2. Add linker flags (-lpthread)
    Single Header
    1. Place crow_all.h inside your project folder and add it to the project in XCode (you need to use File -> Add files to \"project_name\")
    2. Add header search paths for asio's folder:
    3. /usr/local/include, and
    4. Silicon: /opt/homebrew/Cellar/asio/<asio_version>/include
    5. Intel: /usr/local/Cellar/asio/<asio_version>/include
    6. Add linker flags (-lpthread for g++, -pthread for clang++)
  5. Write your Crow application in main.cpp (something like the Hello World example will work).

  6. Press \u25b6 to compile and run your Crow application.
"},{"location":"getting_started/setup/macos/#building-crows-testsexamples","title":"Building Crow's tests/examples","text":"

Note

This tutorial can be used for Crow projects built with CMake as well

  1. Download and install Homebrew.
  2. Run brew install cmake asio in your terminal.
  3. Get Crow's source code (the entire source code).
  4. Run the following Commands:
    1. mkdir build
    2. cd build
    3. cmake ..
    4. make -j12

Note

You can add options like `-DCROW_FEATURES=\"ssl;compression\"` or `-DCROW_AMALGAMATE` to `cmake ..` to build optional tests/examples for HTTP Compression or HTTPS.\n
"},{"location":"getting_started/setup/macos/#compiling-using-a-compiler-directly","title":"Compiling using a compiler directly","text":"

All you need to do is run the following command:

g++ main.cpp -lpthread\n

Note

You'll need to install GCC via brew install gcc. the Clang compiler should be part of XCode or XCode command line tools.

You can use arguments like -DCROW_ENABLE_DEBUG, -DCROW_ENABLE_COMPRESSION -lz for HTTP Compression, or -DCROW_ENABLE_SSL -lssl for HTTPS support, or even replace g++ with clang++.

If GCC throws errors and your program does not compile, you may be using C++03 instead of \u2265C++11. Use the flag -std=c++11.

"},{"location":"getting_started/setup/windows/","title":"Windows","text":"

Here's how you can install Crow on your Windows machine.

"},{"location":"getting_started/setup/windows/#getting-and-compiling-crow","title":"Getting and Compiling Crow","text":""},{"location":"getting_started/setup/windows/#using-a-package-manager","title":"Using A package manager","text":""},{"location":"getting_started/setup/windows/#vcpkg","title":"VCPKG","text":"

Crow can be simply installed through VCPKG using the command vcpkg install crow

"},{"location":"getting_started/setup/windows/#manually-source-or-release","title":"Manually (source or release)","text":""},{"location":"getting_started/setup/windows/#microsoft-visual-studio-and-vcpkg","title":"Microsoft Visual Studio and VCPKG","text":"

The following guide will use example_with_all.cpp as the Crow application for demonstration purposes. VCPKG will be used only to install Crow's dependencies.

  1. Generate crow_all.h by navigating to the scripts folder and running python3 merge_all.py ..\\include crow_all.h.
  2. git clone https://github.com/microsoft/vcpkg.git
  3. .\\vcpkg\\bootstrap-vcpkg.bat
  4. .\\vcpkg\\vcpkg integrate install
  5. Create empty Visual Studio project.
  6. In solution explorer, right click the name of your project then click Open Folder in File Explorer.
  7. Copy crow_all.h, example_with_all.cpp, vcpkg.json to opened folder.
  8. Add crow_all.h to Header Files and example_with_all.cpp to Source Files.
  9. In solution explorer, right click the name of your project then click Properties.
  10. Under vcpkg, set Use Vcpkg Manifest to Yes and Additional Options to --feature-flags=\"versions\".
  11. Set Debug/Release and x64/x86.
  12. Run.
"},{"location":"guides/app/","title":"App","text":"

A Crow app defines an interface to allow the developer access to all the different parts of the framework, without having to manually deal with each one. An app allows access to the HTTP server (for handling connections), router (for handling URLs and requests), Middlewares (for extending Crow), among many others.

Crow has 2 different app types:

"},{"location":"guides/app/#simpleapp","title":"SimpleApp","text":"

Has no middlewares.

"},{"location":"guides/app/#appm1-m2","title":"App<m1, m2, ...>","text":"

Has middlewares.

"},{"location":"guides/app/#using-the-app","title":"Using the app","text":"

To use a Crow app, simply define crow::SimpleApp or crow::App<m1, m2 ...> if you're using middlewares. The methods of an app can be chained. That means that you can configure and run your app in the same code line.

app.bindaddr(\"192.168.1.2\").port(443).ssl_file(\"certfile.crt\",\"keyfile.key\").multithreaded().run();\n
Or if you like your code neat
app.bindaddr(\"192.168.1.2\")\n.port(443)\n.ssl_file(\"certfile.crt\",\"keyfile.key\")\n.multithreaded()\n.run();\n

Note

The run() method is blocking. To run a Crow app asynchronously run_async() should be used instead.

Warning

When using run_async(), make sure to use a variable to save the function's output (such as auto _a = app.run_async()). Otherwise the app will run synchronously.

For more info on middlewares, check out this page. For more info on what functions are available to a Crow app, go here.

"},{"location":"guides/auth/","title":"HTTP Authorization","text":"

While Crow doesn't directly support HTTP authentication, it does provide all the tools you need to build your own. This tutorial will show you how to setup basic and token authentication using Crow.

"},{"location":"guides/auth/#shared-information","title":"Shared information","text":"

Every way boils down to the same basic flow: - The handler calls a verification function. - The handler provides a request and \\<optionally> a response. - The function returns a bool or enum status. - Handler either continues or stops executing based on the returned status. - Either the function or handler modify and end() the response in case of failure.

For the purposes of this tutorial, we will assume that the verification function is defined as bool verify(crow::request req, crow::response res)

"},{"location":"guides/auth/#basic-auth","title":"Basic Auth","text":"

Basic HTTP authentication requires the client to send the Username and Password as a single string, separated by a colon (':') and then encoded as Base64. This data needs to be placed in the Authorization header of the request. A sample header using the credentials \"Username\" and \"Password\" would look like this: Authorization: Basic VXNlcm5hbWU6UGFzc3dvcmQ=.

We don't need to worry about creating the request, we only need to extract the credentials from the Authorization header and verify them.

Note

There are multiple ways to verify the credentials. Most involve checking the username in a database, then checking a hash of the password against the stored password hash for that username. This tutorial will not go over them

To do this we first need to get the Authorization header as a string by using the following code:

std::string myauth = req.get_header_value(\"Authorization\");\n

Next we need to isolate our encoded credentials and decode them as follows:

std::string mycreds = myauth.substr(6);\nstd::string d_mycreds = crow::utility::base64decode(mycreds, mycreds.size());\n

Now that we have our username:password string, we only need to separate it into 2 different strings and verify their validity:

size_t found = d_mycreds.find(':');\nstd::string username = d_mycreds.substr(0, found);\nstd::string password = d_mycreds.substr(found+1);\n\n/*Verify validity of username and password here*/\nreturn true; //or false if the username/password are invalid\n

"},{"location":"guides/auth/#token-auth","title":"Token Auth","text":"

Tokens are some form of unique data that a server can provide to a client in order to verify the client's identity later. While on the surface level they don't provide more security than a strong password, they are designed to be less valuable by being temporary and providing limited access. Variables like expiration time and access scopes are heavily reliant on the implementation however.

"},{"location":"guides/auth/#access-tokens","title":"Access Tokens","text":"

The kind of the token itself can vary depending on the implementation and project requirements: Many services use randomly generated strings as tokens. Then compare them against a database to retrieve the associated user data. Some services however prefer using data bearing tokens. One example of the latter kind is JWT, which uses JSON strings encoded in Base64 and signed using a private key or an agreed upon secret. While this has the added hassle of signing the token to ensure that it's not been tampered with. It does allow for the client to issue tokens without ever needing to present a password or contact a server. The server would simply be able to verify the signature using the client's public key or secret.

"},{"location":"guides/auth/#using-an-access-token","title":"Using an Access Token","text":"

Authenticating with an access token usually involves 2 stages: The first being acquiring the access token from an authority (either by providing credentials such as a username and a password to a server or generating a signed token). The scope of the token (what kind of information it can read or change) is usually defined in this step.

The second stage is simply presenting the Token to the server when requesting a resource. This is even simpler than using basic authentication. All the client needs to do is provide the Authorization header with a keyword (usually Bearer) followed by the token itself (for example: Authorization: Bearer ABC123). Once the client has done that the server will need to acquire this token, which can easily be done as follows:

std::string myauth = req.get_header_value(\"Authorization\");\nstd::string mycreds = myauth.substr(7); // The length can change based on the keyword used\n\n/*Verify validity of the token here*/\nreturn true; //or false if the token is invalid\n
The way of verifying the token is largely up to the implementation, and involves either Bearer token decoding and verification, or database access, neither of which is in this tutorial's scope.

"},{"location":"guides/auth/#refresh-tokens","title":"Refresh Tokens","text":"

Some services may choose to provide a refresh token alongside the access token. This token can be used to request a new access token if the existing one has expired. It provides convenience and security in that it makes it possible to acquire new access tokens without the need to expose a password. The downside however is that it can allow a malicious entity to keep its access to a compromised account. As such refresh tokens need to be handled with care, kept secure, and always invalidated as soon as a client logs out or requests a new access token.

"},{"location":"guides/auth/#sessions","title":"Sessions","text":"

While Crow does not provide built in support for user sessions, a community member was kind enough to provide their own implementation on one of the related issue, their comment along with the code is available here (Please keep in mind that while we appreciate all efforts to push Crow forward, we cannot provide support for this implementation unless it becomes part of the core project).

"},{"location":"guides/base64/","title":"Base64","text":""},{"location":"guides/base64/#encoding","title":"Encoding","text":"

Using crow::utility::base64encode(mystring, mystring.size()) will return a Base64 encoded string. For URL safe Base64 crow::utility::base64encode_urlsafe(mystring, mystring.size()) can be used. The key used in the encoding process can be changed, it is a string containing all 64 characters to be used.

"},{"location":"guides/base64/#decoding","title":"Decoding","text":"

v1.0

Using crow::utility::base64decode(mystring, mystring.size()) with mystring being a Base64 encoded string will return a plain-text string. The function works with both normal and URL safe Base64. However it cannot decode a Base64 string encoded with a custom key.

"},{"location":"guides/blueprints/","title":"Blueprints","text":"

v1.0

Crow supports Flask-style blueprints. A blueprint is a limited app. It cannot handle networking, but it can handle routes. Blueprints allow developers to compartmentalize their Crow applications, making them much more modular.

In order for a blueprint to work, it has to be registered with a Crow app before the app is run. This can be done using app.register_blueprint(blueprint);.

Blueprints let you do the following:

"},{"location":"guides/blueprints/#define-routes","title":"Define Routes","text":"

You can define routes in a blueprint, similarly to how CROW_ROUTE(app, \"/xyz\") works, you can use CROW_BP_ROUTE(blueprint, \"/xyz\") to define a blueprint route.

"},{"location":"guides/blueprints/#define-a-prefix","title":"Define a Prefix","text":"

Blueprints can have a prefix assigned to them. This can be done when creating a new blueprint as in crow::blueprint bp(\"prefix\");. This prefix will be applied to all routes belonging to the blueprint, turning a route such as /crow/rocks into /prefix/crow/rocks.

Warning

Unlike routes, blueprint prefixes should contain no slashes.

"},{"location":"guides/blueprints/#use-a-custom-static-directory","title":"Use a custom Static directory","text":"

Blueprints let you define a custom static directory (relative to your working directory). This can be done by initializing a blueprint as crow::blueprint bp(\"prefix\", \"custom_static\");. This does not have an effect on set_static_file_info(), it's only for when you want direct access to a file.

Note

Currently changing which endpoint the blueprint uses isn't possible, so whatever you've set in CROW_STATIC_ENDPOINT (default is \"static\") will be used. Making your final route /prefix/static/filename.

"},{"location":"guides/blueprints/#use-a-custom-templates-directory","title":"Use a custom Templates directory","text":"

Similar to static directories, You can set a custom templates directory (relative to your working directory). To do this you initialize the blueprint as crow::blueprint bp(\"prefix\", \"custom_static\", \"custom_templates\");. Any routes defined for the blueprint will use that directory when calling crow::mustache::load(\"filename.html\").

Note

If you want to define a custom templates directory without defining a custom static directory, you can pass the static directory as an empty string. Making your constructor crow::blueprint bp(\"prefix\", \"\", \"custom_templates\");.

"},{"location":"guides/blueprints/#define-a-custom-catchall-route","title":"Define a custom Catchall route","text":"

You can define a custom catchall route for a blueprint by calling CROW_BP_CATCHALL_ROUTE(blueprint). This causes any requests with a URL starting with /prefix and no route found to call the blueprint's catchall route. If no catchall route is defined, Crow will default to either the parent blueprint or the app's catchall route.

"},{"location":"guides/blueprints/#register-other-blueprints","title":"Register other Blueprints","text":"

Blueprints can also register other blueprints. This is done through blueprint.register_blueprint(blueprint_2);. The child blueprint's routes become /prefix/prefix_2/abc/xyz.

"},{"location":"guides/compression/","title":"Compression","text":"

v0.3

Crow supports Zlib compression using Gzip or Deflate algorithms.

"},{"location":"guides/compression/#http-compression","title":"HTTP Compression","text":"

HTTP compression is by default disabled in crow. Do the following to enable it: - Define CROW_ENABLE_COMPRESSION in your compiler definitions (g++ main.cpp -DCROW_ENABLE_COMPRESSION for example) or set(CROW_FEATURES compression) in CMakeLists.txt. - Call use_compression(crow::compression::algorithm) on your Crow app. - When compiling your application, make sure that ZLIB is included as a dependency. Either through -lz compiler argument or find_package(ZLIB) in CMake.

Note

3rd point is not needed for MSVC or CMake projects using Crow::Crow since vcpkg.json and Crow's target already include zlib as a dependency.

For the compression algorithm you can use crow::compression::algorithm::DEFLATE or crow::compression::algorithm::GZIP. And now your HTTP responses will be compressed.

"},{"location":"guides/compression/#websocket-compression","title":"Websocket Compression","text":"

Crow currently does not support Websocket compression. Feel free to discuss the subject with us on GitHub if you're feeling adventurous and want to try to implement it. We appreciate all the help.

"},{"location":"guides/included-middleware/","title":"Included Middlewares","text":"

Crow contains some middlewares that are ready to be used in your application. Make sure you understand how to enable and use middleware.

"},{"location":"guides/included-middleware/#sessions","title":"Sessions","text":"

Include: crow/middlewares/session.h Examples: examples/middlewares/session.cpp

This middleware can be used for managing sessions - small packets of data associated with a single client that persist across multiple requests. Sessions shouldn't store anything permanent, but only context that is required to easily work with the current client (is the user authenticated, what page did he visit last, etc.).

"},{"location":"guides/included-middleware/#setup","title":"Setup","text":"

Session data can be stored in multiple ways:

  • crow::InMemoryStore - stores all data in memory
  • crow::FileStore - stores all all data in json files
  • A custom store

Always list the CookieParser before the Session

using Session = crow::SessionMiddleware<crow::FileStore>;\ncrow::App<crow::CookieParser, Session> app{Session{\n  crow::FileStore{\"/tmp/sessiondata\"}\n}};\n

Session ids are represented as random alphanumeric strings and are stored in cookies. See the examples for more customization options.

"},{"location":"guides/included-middleware/#usage","title":"Usage","text":"

A session is basically a key-value map with support for multiple types: strings, integers, booleans and doubles. The map is created and persisted automatically as soon it is first written to.

auto& session = app.get_context<Session>(request);\n\nsession.get(\"key\", \"not-found\"); // get string by key and return \"not-found\" if not found\nsession.get(\"int\", -1);\nsession.get<bool>(\"flag\"); // returns default value(false) if not found\n\nsession.set(\"key\", \"new value\");\nsession.string(\"any-type\"); // return any type as string representation\nsession.remove(\"key\");\nsession.keys(); // return list of keys\n

Session objects are shared between concurrent requests, this means we can perform atomic operations and even lock the object.

session.apply(\"views\", [](int v){return v + 1;}); // this operation is always atomic, no way to get a data race\nsession.mutex().lock(); // manually lock session\n

"},{"location":"guides/included-middleware/#expiration","title":"Expiration","text":"

Expiration can happen either by the cookie expiring or the store deleting \"old\" data.

  • By default, cookies expire after 30 days. This can be changed with the cookie option in the Session constructor.
  • crow::FileStore automatically supports deleting files that are expired (older than 30 days). The expiration age can also be changed in the constructor.

The session expiration can be postponed. This will make the Session issue a new cookie and make the store acknowledge the new expiration time.

session.refresh_expiration()\n

"},{"location":"guides/included-middleware/#cookies","title":"Cookies","text":"

Include: crow/middlewares/cookie_parser.h Examples: examples/middlewares/example_cookies.cpp

This middleware allows to read and write cookies by using CookieParser. Once enabled, it parses all incoming cookies.

Cookies can be read and written with the middleware context. All cookie attributes can be changed as well.

auto& ctx = app.get_context<crow::CookieParser>(request);\nstd::string value = ctx.get_cookie(\"key\");\nctx.set_cookie(\"key\", \"value\")\n    .path(\"/\")\n    .max_age(120);\n

Note

Make sure CookieParser is listed before any other middleware that relies on it.

"},{"location":"guides/included-middleware/#cors","title":"CORS","text":"

Include: crow/middlewares/cors.h Examples: examples/middlewares/example_cors.cpp

This middleware allows to set CORS policies by using CORSHandler. Once enabled, it will apply the default CORS rules globally.

The CORS rules can be modified by first getting the middleware via auto& cors = app.get_middleware<crow::CORSHandler>();. The rules can be set per URL prefix using prefix(), per blueprint using blueprint(), or globally via global(). These will return a CORSRules object which contains the actual rules for the prefix, blueprint, or application. For more details go here.

CORSRules can be modified using the methods origin(), methods(), headers(), max_age(), allow_credentials(), or ignore(). For more details on these methods and what default values they take go here.

auto& cors = app.get_middleware<crow::CORSHandler>();\ncors\n  .global()\n    .headers(\"X-Custom-Header\", \"Upgrade-Insecure-Requests\")\n    .methods(\"POST\"_method, \"GET\"_method)\n  .prefix(\"/cors\")\n    .origin(\"example.com\");\n
"},{"location":"guides/json/","title":"JSON","text":"

Crow has built in support for JSON data.

"},{"location":"guides/json/#type","title":"type","text":"

The types of values that rvalue and wvalue can take are as follows:

  • False: from type bool.
  • True: from type bool.
  • Number
    • Floating_point: from type double.
    • Signed_integer: from type int.
    • Unsigned_integer: from type unsigned int.
  • String: from type std::string.
  • List: from type std::vector.
  • Object: from type crow::json::wvalue or crow::json::rvalue. This last type means that rvalue or wvalue can have keys.
"},{"location":"guides/json/#rvalue","title":"rvalue","text":"

JSON read value, used for taking a JSON string and parsing it into crow::json.

You can read individual items of the rvalue, but you cannot add items to it. To do that, you need to convert it to a wvalue, which can be done by simply writing crow::json::wvalue wval (rval); (assuming rval is your rvalue).

For more info on read values go here.

"},{"location":"guides/json/#wvalue","title":"wvalue","text":"

JSON write value, used for creating, editing and converting JSON to a string.

Note

setting a wvalue to object type can be done by simply assigning a value to whatever string key you like, something like wval[\"key1\"] = val1;. Keep in mind that val1 can be any of the above types.

A wvalue can be treated as an object or even a list (setting a value by using json[3] = 32 for example). Please note that this will remove the data in the value if it isn't of List type.

Warning

JSON does not allow floating point values like NaN or INF, Crow will output null instead of NaN or INF when converting wvalue to a string. ({\"Key\": NaN} becomes {\"Key\": null})

Additionally, a wvalue can be initialized as an object using an initializer list, an example object would be wvalue x = {{\"a\", 1}, {\"b\", 2}}. Or as a list using wvalue x = json::wvalue::list({1, 2, 3}), lists can include any type that wvalue supports.

An object type wvalue uses std::unordered_map by default, if you want to have your returned wvalue key value pairs be sorted (using std::map) you can add #define CROW_JSON_USE_MAP to the top of your program.

A JSON wvalue can be returned directly inside a route handler, this will cause the content-type header to automatically be set to Application/json and the JSON value will be converted to string and placed in the response body. For more information go to Routes.

For more info on write values go here.

Note

Crow's json exceptions can be disabled by using the #define CROW_JSON_NO_ERROR_CHECK macro. This should increase the program speed with the drawback of having unexpected behavious when used incorrectly (e.g. by attempting to parse an invalid json object).

"},{"location":"guides/logging/","title":"Logging","text":"

Crow comes with a simple and easy to use logging system.

Note

Currently Crow's Logger is not linked to the Crow application, meaning if an executable has more than one Crow application they'll be sharing any variables or classes relating to Logging.

"},{"location":"guides/logging/#setting-up-logging-level","title":"Setting up logging level","text":"

You can set up the level at which crow displays logs by using the app's loglevel(crow::LogLevel) method.

The available log levels are as follows (please note that setting a level will also display all logs below this level):

  • Debug
  • Info
  • Warning
  • Error
  • Critical

To set a logLevel, just use app.loglevel(crow::LogLevel::Warning), This will not show any debug or info logs. It will however still show error and critical logs.

Note

Setting the Macro CROW_ENABLE_DEBUG during compilation will also set the log level to Debug (unless otherwise set using loglevel()).

"},{"location":"guides/logging/#writing-a-log","title":"Writing a log","text":"

Writing a log is as simple as CROW_LOG_<LOG LEVEL> << \"Hello\"; (replace<LOG LEVEL> with the actual level in all caps, so you have CROW_LOG_WARNING).

Note

Log times are reported in GMT timezone by default. This is because HTTP requires all reported times for requests and responses to be in GMT. This can be changed by using the macro CROW_USE_LOCALTIMEZONE which will set only the log timezone to the server's local timezone.

"},{"location":"guides/logging/#creating-a-custom-logger","title":"Creating A custom logger","text":"

v1.0

Assuming you have an existing logger or Crow's default format just doesn't work for you. Crow allows you to use a custom logger for any log made using the CROW_LOG_<LOG LEVEL> macro. All you need is a class extending crow::ILogHandler containing the method void log(std::string, crow::LogLevel). Once you have your custom logger, you need to set it via crow::logger::setHandler(&MyLogger);. Here's a full example:

class CustomLogger : public crow::ILogHandler {\n public:\n  CustomLogger() {}\n  void log(std::string message, crow::LogLevel /*level*/) {\n    // \"message\" doesn't contain the timestamp and loglevel\n    // prefix the default logger does and it doesn't end\n    // in a newline.\n    std::cerr << message << std::endl;\n  }\n};\n\nint main(int argc, char** argv) {\n  CustomLogger logger;\n  crow::logger::setHandler(&logger);\n\n  crow::SimpleApp app;\n  CROW_ROUTE(app, \"/\")([]() { return \"Hello\"; });\n  app.run();\n}\n

"},{"location":"guides/middleware/","title":"Middleware","text":"

Middleware is used for altering and inspecting requests before and after calling the handler. In Crow it's very similar to middleware in other web frameworks.

All middleware is registered in the Crow application

crow::App<FirstMW, SecondMW, ThirdMW> app;\n

and is called in this specified order.

Any middleware requires the following 3 members:

  • A context struct for storing request local data.
  • A before_handle method, which is called before the handler.
  • A after_handle method, which is called after the handler.

Warning

As soon as response.end() is called, no other handlers and middleware is run, except for after_handlers of already visited middleware.

"},{"location":"guides/middleware/#example","title":"Example","text":"

A middleware that can be used to guard admin handlers

struct AdminAreaGuard\n{\n    struct context\n    {};\n\n    void before_handle(crow::request& req, crow::response& res, context& ctx)\n    {\n        if (req.remote_ip_address != ADMIN_IP)\n        {\n            res.code = 403;\n            res.end();\n        }\n    }\n\n    void after_handle(crow::request& req, crow::response& res, context& ctx)\n    {}\n};\n
"},{"location":"guides/middleware/#before_handle-and-after_handle","title":"before_handle and after_handle","text":"

There are two possible signatures for before_handle and after_handle

  1. if you only need to access this middleware's context.

    void before_handle(request& req, response& res, context& ctx)\n
  2. To get access to other middlewares context

    template <typename AllContext>\nvoid before_handle(request& req, response& res, context& ctx, AllContext& all_ctx) \n{\n    auto other_ctx = all_ctx.template get<OtherMiddleware>();\n}\n
"},{"location":"guides/middleware/#local-middleware","title":"Local middleware","text":"

By default, every middleware is called for each request. If you want to enable middleware for specific handlers or blueprints, you have to extend it from crow::ILocalMiddleware

struct LocalMiddleware : crow::ILocalMiddleware \n{\n

After this, you can enable it for specific handlers

CROW_ROUTE(app, \"/with_middleware\")\n.CROW_MIDDLEWARES(app, LocalMiddleware)\n([]() {\n    return \"Hello world!\";\n});\n

or blueprints

Blueprint bp(\"with_middleware\");\nbp.CROW_MIDDLEWARES(app, FistLocalMiddleware, SecondLocalMiddleware);\n

Warning

Local and global middleware are called separately. First all global middleware is run, then all enabled local middleware for the current handler is run. In both cases middleware is called strongly in the order listed in the Crow application.

"},{"location":"guides/multipart/","title":"Multipart","text":"

v0.2

Multipart is a way of forming HTTP requests or responses to contain multiple distinct parts.

Such an approach allows a request to contain multiple different pieces of data with potentially conflicting data types in a single response payload. It is typically used either in HTML forms, or when uploading multiple files.

"},{"location":"guides/multipart/#how-multipart-messages-work","title":"How multipart messages work","text":"

The structure of a multipart request is typically consistent of:

  • A Header: Typically multipart/form-data;boundary=<boundary>, This defines the HTTP message as being multipart, as well as defining the separator used to distinguish the different parts.
  • 1 or more parts:
    • --<boundary>
    • Part header: typically content-disposition: mime/type; name=\"<fieldname>\" (mime/type should be replaced with the actual mime-type), can also contain a filename property (separated from the rest by a ; and structured similarly to the name property)
    • Value
  • --<boundary>--
"},{"location":"guides/multipart/#multipart-messages-in-crow","title":"Multipart messages in Crow","text":"

Crow supports multipart requests and responses though crow::multipart::message. A message can be created either by defining the headers, boundary, and individual parts and using them to create the message. or simply by reading a crow::request.

Once a multipart message has been made, the individual parts can be accessed throughout msg.parts, parts is an std::vector.

v1.0

Part headers are organized in a similar way to request and response headers, and can be retrieved via crow::multipart::get_header_object(\"header-key\"). This function returns a crow::multipart::header object.

The message's individual body parts can be accessed by name using msg.get_part_by_name(\"part-name\").

For more info on Multipart messages, go here

"},{"location":"guides/proxies/","title":"Proxies","text":"

You can set Crow up behind any HTTP proxy of your liking, but we will be focusing specifically on 2 of the most popular web server software solutions, Apache2 and Nginx.

A reverse proxy allows you to use Crow without exposing it directly to the internet. It also allows you to, for example, have crow run on a certain specific domain name, subdomain, or even a path, such as domain.abc/crow.

We advise that you set crow up behind some form of reverse proxy if you plan on running a production Crow server that isn't local.

SSL

When using a proxy, make sure that you do not compile Crow with SSL enabled. SSL should be handled by the proxy.

"},{"location":"guides/proxies/#apache2","title":"Apache2","text":"

Assuming you have both Apache2 and the modules proxy, proxy_http, proxy_html (if you plan on serving HTML pages), and proxy_wstunnel (if you plan on using websockets). You will need to enable those modules, which you can do using the following commands:

a2enmod proxy\na2enmod proxy_http\na2enmod proxy_html\na2enmod proxy_wstunnel\n

Next up you'll need to change your configuration (default is /etc/apache2/sites-enabled/000-default.conf) and add the following lines (replace localhost and 40080 with the address and port you defined for your Crow App):

ProxyPass / http://localhost:40080\nProxyPassReverse / http://localhost:40080\n
If you want crow to run in a subdirectory (such as domain.abc/crow) you can use the location tag:
<Location \"/crow\">\n\n    ProxyPass http://localhost:40080\n\n    ProxyPassReverse http://localhost:40080\n\n</Location>\n

Note

If you're using an Arch Linux based OS. You will have to access /etc/httpd/conf/httpd.conf to enable modules and change configuration.

"},{"location":"guides/proxies/#nginx","title":"Nginx","text":"

Setting Nginx up is slightly simpler than Apache, all you need is the Nginx package itself. Once you've installed it, go to the configuration file (usually a .conf file located in /etc/nginx) and add the following lines to your server section (replace localhost and 40080 with the address and port you defined for your Crow App):

location / {\n    proxy_pass http://localhost:40080/;\n    proxy_http_version 1.1;\n}\n
Remember to remove or comment out any existing location / section.

Alternatively, if you want to use a subdirectory, you can simply change the location parameter as such:

location /crow/ {\n    proxy_pass http://localhost:40080/;\n    proxy_http_version 1.1;\n}\n
"},{"location":"guides/query-string/","title":"Query Strings","text":"

A query string is the part of the URL that comes after a ? character, it is usually formatted as key=value&otherkey=othervalue.

Crow supports query strings through crow::request::url_params. The object is of type crow::query_string and can has the following functions:

"},{"location":"guides/query-string/#getname","title":"get(name)","text":"

Returns the value (as char*) based on the given key (or name). Returns nullptr if the key is not found.

"},{"location":"guides/query-string/#popname","title":"pop(name)","text":"

v0.3

Works the same as get, but removes the returned value.

Note

crow::request::url_params is a const value, therefore for pop (also pop_list and pop_dict) to work, a copy needs to be made.

"},{"location":"guides/query-string/#get_listname","title":"get_list(name)","text":"

A URL can be http://example.com?key[]=value1&key[]=value2&key[]=value3. Using get_list(\"key\") on such a URL returns an std::vector<std::string> containing [value1, value2, value3].

get_list(\"key\", false) can be used to parse http://example.com?key=value1&key=value2&key=value3

"},{"location":"guides/query-string/#pop_listname","title":"pop_list(name)","text":"

v0.3

Works the same as get_list but removes all instances of values having the given key (use_brackets is also available here).

"},{"location":"guides/query-string/#get_dictname","title":"get_dict(name)","text":"

Returns an std::unordered_map<std::string, std::string> from a query string such as ?key[sub_key1]=value1&key[sub_key2]=value2&key[sub_key3]=value3. The key in the map is what's in the brackets (sub_key1 for example), and the value being what's after the = sign (value1). The name passed to the function is not part of the returned value.

"},{"location":"guides/query-string/#pop_dictname","title":"pop_dict(name)","text":"

v0.3

Works the same as get_dict but removing the values from the query string.

Warning

if your query string contains both a list and dictionary with the same key, it is best to use pop_list before either get_dict or pop_dict, since a map cannot contain more than one value per key, each item in the list will override the previous and only the last will remain with an empty key.

For more information take a look here.

"},{"location":"guides/routes/","title":"Routes","text":"

Routes define what happens when your client connects to a certain URL.

"},{"location":"guides/routes/#macro","title":"Macro","text":"

CROW_ROUTE(app, url) Can be replaced with app.route<crow::black_magick::get_parameter_tag(url)>(url) or app.route_dynamic(url) if you're using VS2013 or want runtime URL evaluation. Although this usage is NOT recommended.

"},{"location":"guides/routes/#app","title":"App","text":"

Which app class to assign the route to.

"},{"location":"guides/routes/#path-url","title":"Path (URL)","text":"

Which relative path is assigned to the route. Using /hello means the client will need to access http://example.com/hello in order to access the route. A path can have parameters, for example /hello/<int> will allow a client to input an int into the url which will be in the handler (something like http://example.com/hello/42). Parameters can be <int>, <uint>, <double>, <string>, or <path>. It's worth noting that the parameters also need to be defined in the handler, an example of using parameters would be to add 2 numbers based on input:

CROW_ROUTE(app, \"/add/<int>/<int>\")\n([](int a, int b)\n{\n    return std::to_string(a+b);\n});\n
you can see the first <int> is defined as a and the second as b. If you were to run this and call http://example.com/add/1/2, the result would be a page with 3. Exciting!

"},{"location":"guides/routes/#methods","title":"Methods","text":"

You can change the HTTP methods the route uses from just the default GET by using method(), your route macro should look like CROW_ROUTE(app, \"/add/<int>/<int>\").methods(crow::HTTPMethod::GET, crow::HTTPMethod::PATCH) or CROW_ROUTE(app, \"/add/<int>/<int>\").methods(\"GET\"_method, \"PATCH\"_method).

Note

Crow handles OPTIONS method automatically. The HEAD method is handled automatically unless defined in a route. Adding OPTIONS to a route's methods has no effect.

Crow defines the following methods:

DELETE\nGET\nHEAD\nPOST\nPUT\n\nCONNECT\nOPTIONS\nTRACE\n\nPATCH\nPURGE\n\nCOPY\nLOCK\nMKCOL\nMOVE\nPROPFIND\nPROPPATCH\nSEARCH\nUNLOCK\nBIND\nREBIND\nUNBIND\nACL\n\nREPORT\nMKACTIVITY\nCHECKOUT\nMERGE\n\nSEARCH\nNOTIFY\nSUBSCRIBE\nUNSUBSCRIBE\n\nMKCALENDAR\n\nLINK\nUNLINK\n\nSOURCE\n

"},{"location":"guides/routes/#handler","title":"Handler","text":"

Basically a piece of code that gets executed whenever the client calls the associated route, usually in the form of a lambda expression. It can be as simple as ([](){return \"Hello World\"}).

"},{"location":"guides/routes/#request","title":"Request","text":"

Handlers can also use information from the request by adding it as a parameter ([](const crow::request& req){...}).

You can also access the URL parameters in the handler using req.url_params.get(\"param_name\");. If the parameter doesn't exist, nullptr is returned.

Note \u00a0\u00a0\u00a0\u00a0 master

parameters inside the body can be parsed using req.get_body_params();. which is useful for requests of type application/x-www-form-urlencoded. Its format is similar to url_params.

For more information on crow::request go here.

"},{"location":"guides/routes/#response","title":"Response","text":"

Crow also provides the ability to define a response in the parameters by using ([](crow::response& res){...}).

Please note that in order to return a response defined as a parameter you'll need to use res.end();.

Alternatively, you can define the response in the body and return it (([](){return crow::response()})).

For more information on crow::response go here.

Crow defines the following status codes:

100 Continue\n101 Switching Protocols\n\n200 OK\n201 Created\n202 Accepted\n203 Non-Authoritative Information\n204 No Content\n205 Reset Content\n206 Partial Content\n\n300 Multiple Choices\n301 Moved Permanently\n302 Found\n303 See Other\n304 Not Modified\n307 Temporary Redirect\n308 Permanent Redirect\n\n400 Bad Request\n401 Unauthorized\n403 Forbidden\n404 Not Found\n405 Method Not Allowed\n406 Not Acceptable\n407 Proxy Authentication Required\n409 Conflict\n410 Gone\n413 Payload Too Large\n415 Unsupported Media Type\n416 Range Not Satisfiable\n417 Expectation Failed\n428 Precondition Required\n429 Too Many Requests\n451 Unavailable For Legal Reasons\n\n500 Internal Server Error\n501 Not Implemented\n502 Bad Gateway\n503 Service Unavailable\n504 Gateway Timeout\n506 Variant Also Negotiates\n

Note

If your status code is not defined in the list above (e.g. crow::response(123)) Crow will return 500 Internal Server Error instead.

"},{"location":"guides/routes/#return-statement","title":"Return statement","text":"

A crow::response is very strictly tied to a route. If you can have something in a response constructor, you can return it in a handler. The main return type is std::string, although you could also return a crow::json::wvalue or crow::multipart::message directly. For more information on the specific constructors for a crow::response go here.

"},{"location":"guides/routes/#returning-custom-classes","title":"Returning custom classes","text":"

v0.3

If you have your own class you want to return (without converting it to string and returning that), you can use the crow::returnable class. to use the returnable class, you only need your class to publicly extend crow::returnable, add a dump() method that returns your class as an std::string, and add a constructor that has a Content-Type header as a string argument.

Your class should look like the following:

class a : public crow::returnable\n{\n    a() : returnable(\"text/plain\"){};\n\n    ...\n    ...\n    ...\n\n    std::string dump() const override\n    {\n        return this.as_string();\n    }\n}\n

"},{"location":"guides/routes/#response-codes","title":"Response codes","text":"

v1.0

Instead of assigning a response code, you can use the crow::status enum, for example you can replace crow::response(200) with crow::response(crow::status::OK)

"},{"location":"guides/routes/#catchall-routes","title":"Catchall routes","text":"

v0.3

By default, any request that Crow can't find a route for will return a simple 404 response. You can change that to return a default route using the CROW_CATCHALL_ROUTE(app) macro. Defining it is identical to a normal route, even when it comes to the const crow::request& and crow::response& parameters being optional.

Note

For versions higher than 0.3 (excluding patches), Catchall routes handle 404 and 405 responses. The default response will contain the code 404 or 405.

"},{"location":"guides/ssl/","title":"SSL","text":"

Crow supports HTTPS though SSL or TLS.

Note

When mentioning SSL in this documentation, it is often a reference to openSSL, which includes TLS.

To enable SSL, first your application needs to define either a .crt and .key files, or a .pem file. Once you have your files, you can add them to your app like this: app.ssl_file(\"/path/to/cert.crt\", \"/path/to/keyfile.key\") or app.ssl_file(\"/path/to/pem_file.pem\"). Please note that this method can be part of the app method chain, which means it can be followed by .run() or any other method.

You also need to define CROW_ENABLE_SSL in your compiler definitions (g++ main.cpp -DCROW_ENABLE_SSL for example) or set(CROW_FEATURES ssl) in CMakeLists.txt.

You can also set your own SSL context (by using asio::ssl::context ctx) and then applying it via the app.ssl(ctx) method.

Warning

If you plan on using a proxy like Nginx or Apache2, DO NOT use SSL in crow, instead define it in your proxy and keep the connection between the proxy and Crow non-SSL.

"},{"location":"guides/static/","title":"Static Files","text":"

v0.2

A static file is any file that resides in the server's storage.

Crow supports returning static files as responses either implicitly or explicitly.

"},{"location":"guides/static/#implicit","title":"Implicit","text":"

Crow implicitly returns any static files placed in a static directory and any subdirectories, as long as the user calls the endpoint /static/path/to/file. The static folder or endpoint can be changed by defining the macros CROW_STATIC_DIRECTORY \"alternative_directory/\" and CROW_STATIC_ENDPOINT \"/alternative_endpoint/<path>\". static directory changes the directory in the server's file system, while the endpoint changes the URL that the client needs to access.

"},{"location":"guides/static/#explicit","title":"Explicit","text":"

You can directly return a static file by using the crow::response method response.set_static_file_info(\"path/to/file\");. The path is relative to the working directory.

Warning

The path to the file is sanitized by default. it should be fine for most circumstances but if you know what you're doing and need the sanitizer off you can use response.set_static_file_info_unsafe(\"path/to/file\") instead.

Note

Crow sets the content-type header automatically based on the file's extension, if an extension is unavailable or undefined, Crow uses text/plain, if you'd like to explicitly set a content-type, use response.set_header(\"content-type\", \"mime/type\"); AFTER calling set_static_file_info.

Note

Please keep in mind that using the set_static_file_info method means any data already in your response body is ignored and not sent to the client.

"},{"location":"guides/syste/","title":"Systemd run on startup","text":"

Using Systemd allows you to run any executable or script when the system starts. This can be useful when you don't want to re-run your Crow application every single time you restart your server.

"},{"location":"guides/syste/#writing-the-service-unit-file","title":"Writing the Service Unit File","text":"

In order to have Systemd recognize your application, you need to create a .service file that explains how Systemd should handle your program.

To create a service file, you need to go to /etc/systemd/system and create an empty text file with the extension .service, the file name can be anything.

Once the file is created, open it using your favorite text editor and add the following:

[Unit]\nDescription=My revolutionary Crow application\n\nWants=network.target\nAfter=syslog.target network-online.target\n\n[Service]\nType=simple\nExecStart=/absolute/path/to/your/executable\nRestart=on-failure\nRestartSec=10\nKillMode=process\n\n[Install]\nWantedBy=multi-user.target\n

You will then need to give the correct permission, this can be done by using the following command (a sudo maybe required):

chmod 640 /etc/systemd/system/crowthing.service\n

And that's it! You can now use your systemctl controls to enable, start, stop, or disable your Crow application.

If you're not familiar with Systemd, systemctl enable crowthing.service will allow your Crow application to run at startup, start will start it, and the rest is simple.

"},{"location":"guides/templating/","title":"Templating (Mustache)","text":"

Templating is when you return an HTML page with custom data. You can probably tell why that's useful.

Crow supports mustache for templates through its own implementation crow::mustache.

Note

Currently Crow's Mustache implementation is not linked to the Crow application, meaning if an executable has more than one Crow application they'll be sharing any variables or classes relating to template loading and compiling.

"},{"location":"guides/templating/#components-of-mustache","title":"Components of mustache","text":"

There are 2 components of a mustache template implementation:

  • Page
  • Context
"},{"location":"guides/templating/#page","title":"Page","text":"

The HTML page (including the mustache tags). It is usually loaded into crow::mustache::template_t. It needs to be placed in the templates directory which should be directly inside the current working directory of the crow executable.

The templates directory is usually called templates, but can be adjusted per Route (via crow::mustache::set_base(\"new_templates_directory\")), per Blueprint, or globally (via crow::mustache::set_global_base(\"new_templates_directory\"\")).

For more information on how to formulate a template, see this mustache manual.

"},{"location":"guides/templating/#context","title":"Context","text":"

A JSON object containing the tags as keys and their values. crow::mustache::context is actually a crow::json::wvalue.

Note

crow::mustache::context can take a C++ lambda as a value. The lambda needs to take a string as an argument and return a string, such as ctx[lmd] = [&](std::string){return \"Hello World\";};.

Note

The string returned by the lamdba can contain mustache tags, Crow will parse it as any normal template string.

"},{"location":"guides/templating/#returning-a-template","title":"Returning a template","text":"

To return a mustache template, you need to load a page using auto page = crow::mustache::load(\"path/to/template.html\");. Or just simply load a string using auto page = crow::mustache::compile(\"my mustache {{value}}\");. Keep in mind that the path is relative to the templates directory.

Note

You can also use auto page = crow::mustache::load_text(\"path/to/template.html\"); if you want to load a template without mustache processing.

Warning

The path to the template is sanitized by default. it should be fine for most circumstances but if you know what you're doing and need the sanitizer off you can use crow::mustache::load_unsafe() instead.

You also need to set up the context by using crow::mustache::context ctx;. Then you need to assign the keys and values, this can be done the same way you assign values to a JSON write value (ctx[\"key\"] = value;). With your context and page ready, just return page.render(ctx);. This will use the context data to return a filled template. Alternatively you could just render the page without a context using return page.render();.

Note

page.render(); returns a crow::returnable class in order to set the Content-Type header. to get a simple string, use page.render_string() instead.

"},{"location":"guides/testing/","title":"Writing Tests","text":"

Unit tests can be written in 2 ways for a Crow application.

"},{"location":"guides/testing/#the-handler-method","title":"The handler method","text":"

Crow allows users to handle requests that may not come from the network. This is done by calling the handle(req, res) method and providing a request and response objects. Which causes crow to identify and run the appropriate handler, returning the resulting response.

  CROW_ROUTE(app, \"/place\")\n  ([] { return \"hi\"; });\n\n  app.validate();  //Used to make sure all the route handlers are in order.\n\n  {\n    request req;\n    response res;\n\n    req.url = \"/place\";\n\n    app.handle(req, res); //res will contain a code of 200, and a response body of \"hi\"\n  }\n

Note

This method is the simpler of the two and is usually all you really need to test your routes.

Warning

This method does not send any data, nor does it run any post handle code, so things like static file serving (as far as sending the actual data) or compression cannot be tested using this method.

"},{"location":"guides/testing/#the-client-method","title":"The client method","text":"

This method involves creating a simple ASIO client that sends the request and receives the response. It is considerably more complex than the earlier method, but it is both more realistic and includes post handle operations.

  static char buf[2048];\n  SimpleApp app;\n  CROW_ROUTE(app, \"/\")([] { return \"A\"; });\n\n  auto _ = async(launch::async,[&] { app1.bindaddr(\"127.0.0.1\").port(45451).run(); });\n  app.wait_for_server_start();\n\n  std::string sendmsg = \"GET /\\r\\nContent-Length:3\\r\\nX-HeaderTest: 123\\r\\n\\r\\nA=B\\r\\n\";\n  asio::io_service is;\n  {\n    asio::ip::tcp::socket c(is);\n    c.connect(asio::ip::tcp::endpoint(asio::ip::address::from_string(\"127.0.0.1\"), 45451));\n\n    c.send(asio::buffer(sendmsg));\n\n    size_t recved = c.receive(asio::buffer(buf, 2048));\n    CHECK('A' == buf[recved - 1]); //This is specific to catch2 testing library, but it should give a general idea of how to read the response.\n  }\n\n  app.stop(); //THIS MUST RUN\n}\n
The first part is straightforward, create an app and add a route. The second part is launching the app asynchronously and waiting until it starts. The third is formulating our HTTP request string, the format is:
METHOD /\nContent-Length:123\nheader1:value1\nheader2:value2\n\nBODY\n
Next an io_service is created, then a TCP socket is created with the io_service and is connected to the application. Then send the HTTP request string through the socket inside a buffer, and read the result into the buffer in line 1. Finally check the result against the expected one.

Warning

Be absolutely sure that the line app.stop() runs, whether the test fails or succeeds. Not running it WILL CAUSE OTHER TESTS TO FAIL AND THE TEST TO HANG UNTIL THE PROCESS IS TERMINATED.

"},{"location":"guides/websockets/","title":"Websockets","text":"

Websockets are a way of connecting a client and a server without the request response nature of HTTP.

"},{"location":"guides/websockets/#routes","title":"Routes","text":"

To create a websocket in Crow, you need a websocket route. A websocket route differs from a normal route quite a bit. It uses a slightly altered CROW_WEBSOCKET_ROUTE(app, \"/url\") macro, which is then followed by a series of methods (with handlers inside) for each event. These are (sorted by order of execution):

  • onaccept([&](const crow::request& req, void** userdata){handler code goes here})
  • onopen([&](crow::websocket::connection& conn){handler code goes here})
  • onmessage([&](crow::websocket::connection& conn, const std::string& message, bool is_binary){handler code goes here})
  • onerror([&](crow::websocket::connection& conn, const std::string& error_message){handler code goes here})
  • onclose([&](crow::websocket::connection& conn, const std::string& reason){handler code goes here})

Note

onaccept must return a boolean. In case false is returned, the connection is shut down, deleted, and no further communication is done.

Warning

By default, Crow allows clients to send unmasked websocket messages. This is useful for debugging, but goes against the protocol specifications. Production Crow applications should enforce the protocol by adding #define CROW_ENFORCE_WS_SPEC to their source code.

These event methods and their handlers can be chained. The full route should look similar to this:

CROW_WEBSOCKET_ROUTE(app, \"/ws\")\n    .onopen([&](crow::websocket::connection& conn){\n            do_something();\n            })\n    .onclose([&](crow::websocket::connection& conn, const std::string& reason){\n            do_something();\n            })\n    .onmessage([&](crow::websocket::connection& /*conn*/, const std::string& data, bool is_binary){\n                if (is_binary)\n                    do_something(data);\n                else\n                    do_something_else(data);\n            });\n

"},{"location":"guides/websockets/#maximum-payload-size","title":"Maximum payload size","text":"

master

The maximum payload size that a connection accepts can be adjusted either globally by using app.websocket_max_payload(<value in bytes>) or per route by using CROW_WEBSOCKET_ROUTE(app, \"/url\").max_payload(<value in bytes>). In case a message was sent that exceeded the limit. The connection would be shut down and onerror would be triggered.

Note

By default, this limit is disabled. To disable the global setting in specific routes, you only need to call CROW_WEBSOCKET_ROUTE(app, \"/url\").max_payload(UINT64_MAX).

For more info about websocket routes go here.

For more info about websocket connections go here.

"}]} \ No newline at end of file diff --git a/1.2/sitemap.xml b/1.2/sitemap.xml new file mode 100644 index 000000000..64f0bb8fd --- /dev/null +++ b/1.2/sitemap.xml @@ -0,0 +1,128 @@ + + + + https://crowcpp.org/1.2/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/getting_started/a_simple_webpage/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/getting_started/your_first_application/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/getting_started/setup/linux/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/getting_started/setup/macos/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/getting_started/setup/windows/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/app/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/auth/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/base64/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/blueprints/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/compression/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/included-middleware/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/json/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/logging/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/middleware/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/multipart/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/proxies/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/query-string/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/routes/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/ssl/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/static/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/syste/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/templating/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/testing/ + 2024-05-28 + daily + + + https://crowcpp.org/1.2/guides/websockets/ + 2024-05-28 + daily + + \ No newline at end of file diff --git a/1.2/sitemap.xml.gz b/1.2/sitemap.xml.gz new file mode 100644 index 000000000..3d9926a34 Binary files /dev/null and b/1.2/sitemap.xml.gz differ diff --git a/1.2/stylesheets/Lato-Medium.ttf b/1.2/stylesheets/Lato-Medium.ttf new file mode 100644 index 000000000..4684a7e14 Binary files /dev/null and b/1.2/stylesheets/Lato-Medium.ttf differ diff --git a/1.2/stylesheets/colors.css b/1.2/stylesheets/colors.css new file mode 100644 index 000000000..102d93b1b --- /dev/null +++ b/1.2/stylesheets/colors.css @@ -0,0 +1,92 @@ +[data-md-color-scheme="crow-light"]{ + + --md-primary-fg-color: #24404f; + --md-accent-fg-color: #122027; + --md-typeset-a-color: var(--md-accent-fg-color) !important; + --md-default-bg-color: #e5f2f8; + --md-code-bg-color: #cfcfcf !important; + --md-code-hl-comment-color: var(--md-code-fg-color) !important; + --md-code-hl-generic-color: var(--md-code-fg-color) !important; + --md-code-hl-variable-color: var(--md-code-fg-color) !important; + --md-code-fg-color: #1d1d1d !important; + --md-code-hl-punctuation-color: #1d1d1d !important; + --home-border-color: #00000080; + --home-shadow-color: #00000040; + --home-image-border: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgb(0, 0, 0) 50%, rgba(0,0,0,0) 100%); + --md-default-tag-bg-color: var(--md-default-bg-color); + +} + +[data-md-color-scheme="crow-dark"]{ + + --md-primary-fg-color: #24404f; + --md-accent-fg-color: #445e6d; + --md-default-fg-color: rgba(255, 255, 255, 0.87); + --md-typeset-color: rgba(255, 255, 255, 0.80); + --md-admonition-fg-color: rgba(255, 255, 255, 0.80); + --md-default-fg-color--light: rgba(255, 255, 255, 0.54); + --md-default-fg-color--lighter: rgba(255, 255, 255, 0.32); + --md-default-fg-color--lightest: rgba(255, 255, 255, 0.07); + --md-typeset-a-color: var(--md-accent-fg-color) !important; + --md-default-bg-color: #1a2124; + --md-code-bg-color: #101010 !important; + --md-code-hl-comment-color: var(--md-code-fg-color) !important; + --md-code-hl-generic-color: var(--md-code-fg-color) !important; + --md-code-hl-variable-color: var(--md-code-fg-color) !important; + --md-code-hl-operator-color: var(--md-code-fg-color) !important; + --md-code-fg-color: #cfcfcf !important; + --md-code-hl-punctuation-color: #adadad !important; + --home-border-color: #ffffff20; + --home-shadow-color: #00000040; + --home-image-border: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0) 100%); + --md-admonition-bg-color: #272a2b; + --md-code-hl-color: rgba(255, 255, 0, 0.18); + --md-default-tag-bg-color: var(--md-default-fg-color); + +} + +.md-typeset .md-button { + color: var(--md-default-fg-color--light); + border-radius: 0.5rem; +} + +/* +:root{ + --md-default-fg-color: rgba(255, 255, 255, 0.87); + --md-default-fg-color--light: rgba(255, 255, 255, 0.54); + --md-default-fg-color--lighter: rgba(255, 255, 255, 0.32); + --md-default-fg-color--lightest: rgba(255, 255, 255, 0.07); + --md-default-bg-color: #1a2124; + --md-typeset-a-color: var(--md-accent-fg-color) !important; +} + +.md-typeset code { + background-color: #2f2f2f; +} + + +.highlight .c, .highlight .c1, .highlight .ch, .highlight .cm, .highlight .cs, .highlight .sd { + color: #606060 !important; +} + +.linenos { + background-color: #cfcfcf !important; + color: #1d1d1d !important; +} + +.highlighttable .linenodiv pre { + background-color: #cfcfcf !important; + color: #1d1d1d !important; +} + +.highlight .p { + color: #1d1d1d; +} + +.highlight .o { + color: #1d1d1d; +} + +.highlight .n { + color: #1d1d1d; +} diff --git a/1.2/stylesheets/extra.css b/1.2/stylesheets/extra.css new file mode 100644 index 000000000..5f8c7549d --- /dev/null +++ b/1.2/stylesheets/extra.css @@ -0,0 +1,61 @@ +.md-header__source { + margin-left: 0px; + width: autho; + min-width: 9.6rem; +} + +.md-typeset code { + border-radius: .25rem !important; +} + +.code { + border-radius: .25rem !important; +} + +.tag +{ + background-color: var(--md-primary-fg-color); + color: var(--md-default-tag-bg-color); + border-radius: 50px; + padding-left: 0.15em; + padding-right: 0.35em; + padding-top: 0.45em; + padding-bottom: 0.35em; +} + +.tag a +{ + color: var(--md-default-tag-bg-color); +} + +.tag a:hover +{ + color: var(--md-default-tag-bg-color); +} + +.md-typeset :is(.emojione, .twemoji, .gemoji) +{ + vertical-align: text-bottom; +} + +.md-typeset :is(.emojione, .twemoji, .gemoji) svg +{ + width: 1.25em; +} + +[data-md-color-scheme="crow-dark"] img[src$="#only-dark"] +{ + display: block; +} +[data-md-color-scheme="crow-light"] img[src$="#only-light"] +{ + display: block; +} +[data-md-color-scheme="crow-light"] img[src$="#only-dark"] +{ + display: none; +} +[data-md-color-scheme="crow-dark"] img[src$="#only-light"] +{ + display: none; +} diff --git a/1.2/stylesheets/latofonts.css b/1.2/stylesheets/latofonts.css new file mode 100644 index 000000000..97049c0ac --- /dev/null +++ b/1.2/stylesheets/latofonts.css @@ -0,0 +1,10 @@ +/* Webfont: Lato-Medium */@font-face { + font-family: 'Lato'; + src: url('Lato-Medium.ttf') format('truetype'); + font-style: normal; + font-weight: normal; + text-rendering: optimizeLegibility; +} +body, input { + font-family: "Lato", -apple-system, Helvetica, Arial, sans-serif; +} diff --git a/1.2/versions.json b/1.2/versions.json new file mode 100644 index 000000000..9e56addec --- /dev/null +++ b/1.2/versions.json @@ -0,0 +1,7 @@ +[ + {"version": "master", "title": "master", "aliases": []}, + {"version": "1.2", "title": "1.2.0", "aliases": []}, + {"version": "1.1", "title": "1.1.0", "aliases": []}, + {"version": "1.0", "title": "1.0+3", "aliases": []}, + {"version": "0.3", "title": "0.3+4", "aliases": []} +] diff --git a/versions.json b/versions.json index 5d70ed1e7..a44878f37 100644 --- a/versions.json +++ b/versions.json @@ -4,6 +4,11 @@ "title": "master", "aliases": [] }, + { + "version": "1.2", + "title": "1.2", + "aliases": [] + }, { "version": "1.1", "title": "1.1",
+ +
+
TinySHA1.hpp File Reference
+