/* ** This function is similar to sqlite3ExprDup(), except that if pzBuffer ** is not NULL then *pzBuffer is assumed to point to a buffer large enough ** to store the copy of expression p, the copies of p->u.zToken ** (if applicable), and the copies of the p->pLeft and p->pRight expressions, ** if any. Before returning, *pzBuffer is set to the first byte passed the ** portion of the buffer copied into by this function. */ static Expr exprDup( sqlite3 db, Expr p, int flags, ref Expr pzBuffer ) { Expr pNew = null; /* Value to return */ if ( p != null ) { bool isReduced = ( flags & EXPRDUP_REDUCE ) != 0; Expr zAlloc = new Expr(); u32 staticFlag = 0; Debug.Assert( pzBuffer == null || isReduced ); /* Figure out where to write the new Expr structure. */ //if ( pzBuffer !=null) //{ // zAlloc = pzBuffer; // staticFlag = EP_Static; //} //else //{ // zAlloc = new Expr();//sqlite3DbMallocRaw( db, dupedExprSize( p, flags ) ); //} pNew = p.Copy_Minimal();// (Expr*)zAlloc; if ( pNew != null ) { /* Set nNewSize to the size allocated for the structure pointed to ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed ** by the copy of the p->u.zToken string (if any). */ int nStructSize = dupedExprStructSize( p, flags ); int nNewSize = nStructSize & 0xfff; int nToken; if ( !ExprHasProperty( p, EP_IntValue ) && !String.IsNullOrEmpty( p.u.zToken ) ) { nToken = sqlite3Strlen30( p.u.zToken ); } else { nToken = 0; } if ( isReduced ) { Debug.Assert( !ExprHasProperty( p, EP_Reduced ) ); //memcpy( zAlloc, p, nNewSize ); } else { int nSize = exprStructSize( p ); //memcpy( zAlloc, p, nSize ); //memset( &zAlloc[nSize], 0, EXPR_FULLSIZE - nSize ); } /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */ unchecked { pNew.flags &= (ushort)( ~( EP_Reduced | EP_TokenOnly | EP_Static ) ); } pNew.flags |= (ushort)( nStructSize & ( EP_Reduced | EP_TokenOnly ) ); pNew.flags |= (ushort)staticFlag; /* Copy the p->u.zToken string, if any. */ if ( nToken != 0 ) { string zToken;// = pNew.u.zToken = (char*)&zAlloc[nNewSize]; zToken = p.u.zToken.Substring( 0, nToken );// memcpy( zToken, p.u.zToken, nToken ); } if ( 0 == ( ( p.flags | pNew.flags ) & EP_TokenOnly ) ) { /* Fill in the pNew.x.pSelect or pNew.x.pList member. */ if ( ExprHasProperty( p, EP_xIsSelect ) ) { pNew.x.pSelect = sqlite3SelectDup( db, p.x.pSelect, isReduced ? 1 : 0 ); } else { pNew.x.pList = sqlite3ExprListDup( db, p.x.pList, isReduced ? 1 : 0 ); } } /* Fill in pNew.pLeft and pNew.pRight. */ if ( ExprHasAnyProperty( pNew, EP_Reduced | EP_TokenOnly ) ) { //zAlloc += dupedExprNodeSize( p, flags ); if ( ExprHasProperty( pNew, EP_Reduced ) ) { pNew.pLeft = exprDup( db, p.pLeft, EXPRDUP_REDUCE, ref zAlloc ); pNew.pRight = exprDup( db, p.pRight, EXPRDUP_REDUCE, ref zAlloc ); } if ( pzBuffer != null ) { pzBuffer = zAlloc; } } else { pNew.flags2 = 0; if ( !ExprHasAnyProperty( p, EP_TokenOnly ) ) { pNew.pLeft = sqlite3ExprDup( db, p.pLeft, 0 ); pNew.pRight = sqlite3ExprDup( db, p.pRight, 0 ); } } } } return pNew; }