mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
More optimizations. (CVS 813)
FossilOrigin-Name: 5809132f5bf40bae2331f887e87fe5baecc15c46
This commit is contained in:
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
|||||||
C Parameterize\sthe\snumber\sof\sadjacent\spages\sthat\sparticipate\sin\sthe\sbalancing\nalgorithm\sin\sthe\sBTree.\s\sBut\sleave\sthe\ssetting\sat\sthe\scurrent\svalue\sof\s3.\s(CVS\s812)
|
C More\soptimizations.\s(CVS\s813)
|
||||||
D 2003-01-04T19:44:08
|
D 2003-01-05T21:41:41
|
||||||
F Makefile.in 868c17a1ae1c07603d491274cc8f86c04acf2a1e
|
F Makefile.in 868c17a1ae1c07603d491274cc8f86c04acf2a1e
|
||||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@ -18,7 +18,7 @@ F main.mk 9d13839b9697af332d788fe6e801e68da027cc5c
|
|||||||
F publish.sh e5b83867d14708ed58cec8cba0a4f201e969474d
|
F publish.sh e5b83867d14708ed58cec8cba0a4f201e969474d
|
||||||
F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e
|
F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e
|
||||||
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
|
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
|
||||||
F src/btree.c 65dfa86fc2a9eded02fc011c368d20174fba10d1
|
F src/btree.c 131b5903f66e148f0f9af0cedd1c6654932c4e04
|
||||||
F src/btree.h 17710339f7a8f46e3c7d6d0d4648ef19c584ffda
|
F src/btree.h 17710339f7a8f46e3c7d6d0d4648ef19c584ffda
|
||||||
F src/build.c 8569ac014609add4b796260d3567a5090b90056d
|
F src/build.c 8569ac014609add4b796260d3567a5090b90056d
|
||||||
F src/delete.c aad9d4051ab46e6f6391ea5f7b8994a7c05bdd15
|
F src/delete.c aad9d4051ab46e6f6391ea5f7b8994a7c05bdd15
|
||||||
@ -52,7 +52,7 @@ F src/tokenize.c 75e3bb37305b64e118e709752066f494c4f93c30
|
|||||||
F src/trigger.c 5ba917fc226b96065108da28186c2efaec53e481
|
F src/trigger.c 5ba917fc226b96065108da28186c2efaec53e481
|
||||||
F src/update.c 881e4c8e7c786545da4fd2d95da19252b2e31137
|
F src/update.c 881e4c8e7c786545da4fd2d95da19252b2e31137
|
||||||
F src/util.c e2d108842e02810d3d3242cac0e024b09cdb3c4a
|
F src/util.c e2d108842e02810d3d3242cac0e024b09cdb3c4a
|
||||||
F src/vdbe.c 572ee028e01d2811dee1ad4d5161ce82e31e88d4
|
F src/vdbe.c dfcb470866708946dc67028359c3128876ad2297
|
||||||
F src/vdbe.h 754eba497cfe0c3e352b9c101ab2f811f10d0a55
|
F src/vdbe.h 754eba497cfe0c3e352b9c101ab2f811f10d0a55
|
||||||
F src/where.c af235636b7bc7f7f42ee1c7162d1958ad0102cab
|
F src/where.c af235636b7bc7f7f42ee1c7162d1958ad0102cab
|
||||||
F test/all.test 873d30e25a41b3aa48fec5633a7ec1816e107029
|
F test/all.test 873d30e25a41b3aa48fec5633a7ec1816e107029
|
||||||
@ -152,7 +152,7 @@ F www/speed.tcl a20a792738475b68756ea7a19321600f23d1d803
|
|||||||
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
|
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
|
||||||
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
|
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
|
||||||
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
||||||
P 03d20673616cae0dca524fd04557798a98fb7069
|
P 6c304024bbd21a1886a57ada795531349aa627d7
|
||||||
R 131375a6bd5b4a8f3f85a8c7c672f995
|
R fea26809e1516d4617eda0cb040e2e8f
|
||||||
U drh
|
U drh
|
||||||
Z c7e9682e375704261f3906f005af16af
|
Z 448bc2108caef81c9e7977f7eeab8964
|
||||||
|
@ -1 +1 @@
|
|||||||
6c304024bbd21a1886a57ada795531349aa627d7
|
5809132f5bf40bae2331f887e87fe5baecc15c46
|
91
src/btree.c
91
src/btree.c
@ -9,7 +9,7 @@
|
|||||||
** May you share freely, never taking more than you give.
|
** May you share freely, never taking more than you give.
|
||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
** $Id: btree.c,v 1.79 2003/01/04 19:44:08 drh Exp $
|
** $Id: btree.c,v 1.80 2003/01/05 21:41:41 drh Exp $
|
||||||
**
|
**
|
||||||
** This file implements a external (disk-based) database using BTrees.
|
** This file implements a external (disk-based) database using BTrees.
|
||||||
** For a detailed discussion of BTrees, refer to
|
** For a detailed discussion of BTrees, refer to
|
||||||
@ -1338,13 +1338,15 @@ int sqliteBtreeKeyCompare(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Move the cursor down to a new child page.
|
** Move the cursor down to a new child page. The newPgno argument is the
|
||||||
|
** page number of the child page in the byte order of the disk image.
|
||||||
*/
|
*/
|
||||||
static int moveToChild(BtCursor *pCur, int newPgno){
|
static int moveToChild(BtCursor *pCur, int newPgno){
|
||||||
int rc;
|
int rc;
|
||||||
MemPage *pNewPage;
|
MemPage *pNewPage;
|
||||||
Btree *pBt = pCur->pBt;
|
Btree *pBt = pCur->pBt;
|
||||||
|
|
||||||
|
newPgno = SWAB32(pBt, newPgno);
|
||||||
rc = sqlitepager_get(pBt->pPager, newPgno, (void**)&pNewPage);
|
rc = sqlitepager_get(pBt->pPager, newPgno, (void**)&pNewPage);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
rc = initPage(pBt, pNewPage, newPgno, pCur->pPage);
|
rc = initPage(pBt, pNewPage, newPgno, pCur->pPage);
|
||||||
@ -1369,16 +1371,18 @@ static int moveToChild(BtCursor *pCur, int newPgno){
|
|||||||
** right-most child page then pCur->idx is set to one more than
|
** right-most child page then pCur->idx is set to one more than
|
||||||
** the largest cell index.
|
** the largest cell index.
|
||||||
*/
|
*/
|
||||||
static int moveToParent(BtCursor *pCur){
|
static void moveToParent(BtCursor *pCur){
|
||||||
Pgno oldPgno;
|
Pgno oldPgno;
|
||||||
MemPage *pParent;
|
MemPage *pParent;
|
||||||
|
MemPage *pPage;
|
||||||
int idxParent;
|
int idxParent;
|
||||||
pParent = pCur->pPage->pParent;
|
pPage = pCur->pPage;
|
||||||
if( pParent==0 ) return SQLITE_INTERNAL;
|
assert( pPage!=0 );
|
||||||
idxParent = pCur->pPage->idxParent;
|
pParent = pPage->pParent;
|
||||||
oldPgno = sqlitepager_pagenumber(pCur->pPage);
|
assert( pParent!=0 );
|
||||||
|
idxParent = pPage->idxParent;
|
||||||
sqlitepager_ref(pParent);
|
sqlitepager_ref(pParent);
|
||||||
sqlitepager_unref(pCur->pPage);
|
sqlitepager_unref(pPage);
|
||||||
pCur->pPage = pParent;
|
pCur->pPage = pParent;
|
||||||
assert( pParent->idxShift==0 );
|
assert( pParent->idxShift==0 );
|
||||||
if( pParent->idxShift==0 ){
|
if( pParent->idxShift==0 ){
|
||||||
@ -1387,7 +1391,7 @@ static int moveToParent(BtCursor *pCur){
|
|||||||
/* Verify that pCur->idx is the correct index to point back to the child
|
/* Verify that pCur->idx is the correct index to point back to the child
|
||||||
** page we just came from
|
** page we just came from
|
||||||
*/
|
*/
|
||||||
oldPgno = SWAB32(pCur->pBt, oldPgno);
|
oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
|
||||||
if( pCur->idx<pParent->nCell ){
|
if( pCur->idx<pParent->nCell ){
|
||||||
assert( pParent->apCell[idxParent]->h.leftChild==oldPgno );
|
assert( pParent->apCell[idxParent]->h.leftChild==oldPgno );
|
||||||
}else{
|
}else{
|
||||||
@ -1402,7 +1406,7 @@ static int moveToParent(BtCursor *pCur){
|
|||||||
*/
|
*/
|
||||||
int i;
|
int i;
|
||||||
pCur->idx = pParent->nCell;
|
pCur->idx = pParent->nCell;
|
||||||
oldPgno = SWAB32(pCur->pBt, oldPgno);
|
oldPgno = SWAB32(pCur->pBt, sqlitepager_pagenumber(pPage));
|
||||||
for(i=0; i<pParent->nCell; i++){
|
for(i=0; i<pParent->nCell; i++){
|
||||||
if( pParent->apCell[i]->h.leftChild==oldPgno ){
|
if( pParent->apCell[i]->h.leftChild==oldPgno ){
|
||||||
pCur->idx = i;
|
pCur->idx = i;
|
||||||
@ -1410,7 +1414,6 @@ static int moveToParent(BtCursor *pCur){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1440,7 +1443,7 @@ static int moveToLeftmost(BtCursor *pCur){
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
while( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
|
while( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
|
||||||
rc = moveToChild(pCur, SWAB32(pCur->pBt, pgno));
|
rc = moveToChild(pCur, pgno);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
}
|
}
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
@ -1459,7 +1462,7 @@ static int moveToRightmost(BtCursor *pCur){
|
|||||||
|
|
||||||
while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){
|
while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){
|
||||||
pCur->idx = pCur->pPage->nCell;
|
pCur->idx = pCur->pPage->nCell;
|
||||||
rc = moveToChild(pCur, SWAB32(pCur->pBt, pgno));
|
rc = moveToChild(pCur, pgno);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
}
|
}
|
||||||
pCur->idx = pCur->pPage->nCell - 1;
|
pCur->idx = pCur->pPage->nCell - 1;
|
||||||
@ -1569,7 +1572,7 @@ int sqliteBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
pCur->idx = lwr;
|
pCur->idx = lwr;
|
||||||
rc = moveToChild(pCur, SWAB32(pCur->pBt, chldPg));
|
rc = moveToChild(pCur, chldPg);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
}
|
}
|
||||||
/* NOT REACHED */
|
/* NOT REACHED */
|
||||||
@ -1583,19 +1586,19 @@ int sqliteBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
|
|||||||
*/
|
*/
|
||||||
int sqliteBtreeNext(BtCursor *pCur, int *pRes){
|
int sqliteBtreeNext(BtCursor *pCur, int *pRes){
|
||||||
int rc;
|
int rc;
|
||||||
|
MemPage *pPage = pCur->pPage;
|
||||||
assert( pRes!=0 );
|
assert( pRes!=0 );
|
||||||
/* assert( pCur->pPage!=0 ); */
|
if( pPage==0 ){
|
||||||
if( pCur->pPage==0 ){
|
|
||||||
*pRes = 1;
|
*pRes = 1;
|
||||||
return SQLITE_ABORT;
|
return SQLITE_ABORT;
|
||||||
}
|
}
|
||||||
assert( pCur->pPage->isInit );
|
assert( pPage->isInit );
|
||||||
assert( pCur->eSkip!=SKIP_INVALID );
|
assert( pCur->eSkip!=SKIP_INVALID );
|
||||||
if( pCur->pPage->nCell==0 ){
|
if( pPage->nCell==0 ){
|
||||||
*pRes = 1;
|
*pRes = 1;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
assert( pCur->idx<pCur->pPage->nCell );
|
assert( pCur->idx<pPage->nCell );
|
||||||
if( pCur->eSkip==SKIP_NEXT ){
|
if( pCur->eSkip==SKIP_NEXT ){
|
||||||
pCur->eSkip = SKIP_NONE;
|
pCur->eSkip = SKIP_NONE;
|
||||||
*pRes = 0;
|
*pRes = 0;
|
||||||
@ -1603,72 +1606,78 @@ int sqliteBtreeNext(BtCursor *pCur, int *pRes){
|
|||||||
}
|
}
|
||||||
pCur->eSkip = SKIP_NONE;
|
pCur->eSkip = SKIP_NONE;
|
||||||
pCur->idx++;
|
pCur->idx++;
|
||||||
if( pCur->idx>=pCur->pPage->nCell ){
|
if( pCur->idx>=pPage->nCell ){
|
||||||
if( pCur->pPage->u.hdr.rightChild ){
|
if( pPage->u.hdr.rightChild ){
|
||||||
rc = moveToChild(pCur, SWAB32(pCur->pBt, pCur->pPage->u.hdr.rightChild));
|
rc = moveToChild(pCur, pPage->u.hdr.rightChild);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
rc = moveToLeftmost(pCur);
|
rc = moveToLeftmost(pCur);
|
||||||
*pRes = 0;
|
*pRes = 0;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
do{
|
do{
|
||||||
if( pCur->pPage->pParent==0 ){
|
if( pPage->pParent==0 ){
|
||||||
*pRes = 1;
|
*pRes = 1;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
rc = moveToParent(pCur);
|
moveToParent(pCur);
|
||||||
}while( rc==SQLITE_OK && pCur->idx>=pCur->pPage->nCell );
|
pPage = pCur->pPage;
|
||||||
|
}while( pCur->idx>=pPage->nCell );
|
||||||
*pRes = 0;
|
*pRes = 0;
|
||||||
return rc;
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
*pRes = 0;
|
||||||
|
if( pPage->u.hdr.rightChild==0 ){
|
||||||
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
rc = moveToLeftmost(pCur);
|
rc = moveToLeftmost(pCur);
|
||||||
*pRes = 0;
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Step the cursor to the back to the previous entry in the database. If
|
** Step the cursor to the back to the previous entry in the database. If
|
||||||
** successful and pRes!=NULL then set *pRes=0. If the cursor
|
** successful then set *pRes=0. If the cursor
|
||||||
** was already pointing to the first entry in the database before
|
** was already pointing to the first entry in the database before
|
||||||
** this routine was called, then set *pRes=1 if pRes!=NULL.
|
** this routine was called, then set *pRes=1.
|
||||||
*/
|
*/
|
||||||
int sqliteBtreePrevious(BtCursor *pCur, int *pRes){
|
int sqliteBtreePrevious(BtCursor *pCur, int *pRes){
|
||||||
int rc;
|
int rc;
|
||||||
Pgno pgno;
|
Pgno pgno;
|
||||||
if( pCur->pPage==0 ){
|
MemPage *pPage;
|
||||||
if( pRes ) *pRes = 1;
|
pPage = pCur->pPage;
|
||||||
|
if( pPage==0 ){
|
||||||
|
*pRes = 1;
|
||||||
return SQLITE_ABORT;
|
return SQLITE_ABORT;
|
||||||
}
|
}
|
||||||
assert( pCur->pPage->isInit );
|
assert( pPage->isInit );
|
||||||
assert( pCur->eSkip!=SKIP_INVALID );
|
assert( pCur->eSkip!=SKIP_INVALID );
|
||||||
if( pCur->pPage->nCell==0 ){
|
if( pPage->nCell==0 ){
|
||||||
if( pRes ) *pRes = 1;
|
*pRes = 1;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
if( pCur->eSkip==SKIP_PREV ){
|
if( pCur->eSkip==SKIP_PREV ){
|
||||||
pCur->eSkip = SKIP_NONE;
|
pCur->eSkip = SKIP_NONE;
|
||||||
if( pRes ) *pRes = 0;
|
*pRes = 0;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
pCur->eSkip = SKIP_NONE;
|
pCur->eSkip = SKIP_NONE;
|
||||||
assert( pCur->idx>=0 );
|
assert( pCur->idx>=0 );
|
||||||
if( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
|
if( (pgno = pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
|
||||||
rc = moveToChild(pCur, SWAB32(pCur->pBt, pgno));
|
rc = moveToChild(pCur, pgno);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
rc = moveToRightmost(pCur);
|
rc = moveToRightmost(pCur);
|
||||||
}else{
|
}else{
|
||||||
while( pCur->idx==0 ){
|
while( pCur->idx==0 ){
|
||||||
if( pCur->pPage->pParent==0 ){
|
if( pPage->pParent==0 ){
|
||||||
if( pRes ) *pRes = 1;
|
if( pRes ) *pRes = 1;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
rc = moveToParent(pCur);
|
moveToParent(pCur);
|
||||||
if( rc ) return rc;
|
pPage = pCur->pPage;
|
||||||
}
|
}
|
||||||
pCur->idx--;
|
pCur->idx--;
|
||||||
rc = SQLITE_OK;
|
rc = SQLITE_OK;
|
||||||
}
|
}
|
||||||
if( pRes ) *pRes = 0;
|
*pRes = 0;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
src/vdbe.c
18
src/vdbe.c
@ -36,7 +36,7 @@
|
|||||||
** in this file for details. If in doubt, do not deviate from existing
|
** in this file for details. If in doubt, do not deviate from existing
|
||||||
** commenting and indentation practices when changing or adding code.
|
** commenting and indentation practices when changing or adding code.
|
||||||
**
|
**
|
||||||
** $Id: vdbe.c,v 1.189 2003/01/02 14:43:57 drh Exp $
|
** $Id: vdbe.c,v 1.190 2003/01/05 21:41:42 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -780,8 +780,7 @@ static AggElem *_AggInFocus(Agg *p){
|
|||||||
**
|
**
|
||||||
** NULLs are converted into an empty string.
|
** NULLs are converted into an empty string.
|
||||||
*/
|
*/
|
||||||
#define Stringify(P,I) \
|
#define Stringify(P,I) ((aStack[I].flags & STK_Str)==0 ? hardStringify(P,I) : 0)
|
||||||
((P->aStack[I].flags & STK_Str)==0 ? hardStringify(P,I) : 0)
|
|
||||||
static int hardStringify(Vdbe *p, int i){
|
static int hardStringify(Vdbe *p, int i){
|
||||||
Stack *pStack = &p->aStack[i];
|
Stack *pStack = &p->aStack[i];
|
||||||
char **pzStack = &p->zStack[i];
|
char **pzStack = &p->zStack[i];
|
||||||
@ -1404,6 +1403,7 @@ int sqliteVdbeExec(
|
|||||||
int returnDepth = 0; /* Next unused element in returnStack[] */
|
int returnDepth = 0; /* Next unused element in returnStack[] */
|
||||||
#ifdef VDBE_PROFILE
|
#ifdef VDBE_PROFILE
|
||||||
unsigned long long start;
|
unsigned long long start;
|
||||||
|
int origPc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -1443,6 +1443,7 @@ int sqliteVdbeExec(
|
|||||||
for(pc=0; !sqlite_malloc_failed && rc==SQLITE_OK && pc<p->nOp
|
for(pc=0; !sqlite_malloc_failed && rc==SQLITE_OK && pc<p->nOp
|
||||||
VERIFY(&& pc>=0); pc++){
|
VERIFY(&& pc>=0); pc++){
|
||||||
#ifdef VDBE_PROFILE
|
#ifdef VDBE_PROFILE
|
||||||
|
origPc = pc;
|
||||||
start = hwtime();
|
start = hwtime();
|
||||||
#endif
|
#endif
|
||||||
pOp = &p->aOp[pc];
|
pOp = &p->aOp[pc];
|
||||||
@ -5354,8 +5355,15 @@ default: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VDBE_PROFILE
|
#ifdef VDBE_PROFILE
|
||||||
pOp->cycles += hwtime() - start;
|
{
|
||||||
pOp->cnt++;
|
long long elapse = hwtime() - start;
|
||||||
|
pOp->cycles += elapse;
|
||||||
|
pOp->cnt++;
|
||||||
|
#if 0
|
||||||
|
fprintf(stdout, "%10lld ", elapse);
|
||||||
|
vdbePrintOp(stdout, origPc, &p->aOp[origPc]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The following code adds nothing to the actual functionality
|
/* The following code adds nothing to the actual functionality
|
||||||
|
Reference in New Issue
Block a user