📄 ntx.cpp
字号:
if( !TempNode ) return 0; if( TempNode->Type == 'd' ) return TempNode->ResultLen; if( TempNode->Type == 'D' ) { memset( FieldName, 0x00, 11 ); memcpy( FieldName, TempNode->NodeText, TempNode->Len ); Type = dbf->GetFieldType( dbf->GetFieldNo( FieldName )); if( Type == 'N' || Type == 'F' ) return TempNode->ResultLen; } if(( rc = dbf->xbase->ProcessExpression( ExpressionTree )) != XB_NO_ERROR ) return 0; TempNode = (xbExpNode *) dbf->xbase->Pop(); if( !TempNode ) return 0; rc = TempNode->DataLen;// if( !TempNode->InTree ) dbf->xbase->FreeExpNode( TempNode ); if( !TempNode->InTree ) delete TempNode; return rc;}/***********************************************************************///! Short description./*! \param IxName \param Exp \param Unique \param Overlay*/xbShort xbNtx::CreateIndex(const char * IxName, const char * Exp, xbShort Unique, xbShort Overlay ){ xbShort i, NameLen, KeyLen, rc; IndexStatus = XB_CLOSED; if( strlen( Exp ) > 255 ) xb_error( XB_INVALID_KEY_EXPRESSION); if( dbf->GetDbfStatus() == 0 ) xb_error( XB_NOT_OPEN); /* Get the index file name and store it in the class */ NameLen = strlen( IxName ) + 1; if(( rc = dbf->NameSuffixMissing( 4, IxName )) > 0 ) NameLen +=4;/* if(( IndexName = (char *) malloc( NameLen )) == NULL ) {#ifdef HAVE_EXCEPTIONS throw xbOutOfMemoryException();#else return XB_NO_MEMORY;#endif }*/ /* copy the name to the class variable */ IndexName = IxName; if( rc == 1 ) IndexName += ".ntx"; else if( rc == 2 ) IndexName += ".NTX"; /* check if the file already exists */ if (((indexfp = fopen( IndexName, "r" )) != NULL ) && !Overlay ) { fclose( indexfp ); xb_io_error(XB_FILE_EXISTS, IndexName); } else if( indexfp ) fclose( indexfp ); if(( indexfp = fopen( IndexName, "w+b" )) == NULL ){ return XB_OPEN_ERROR; }#ifdef XB_LOCKING_ON /* ** Must turn off buffering when multiple programs may be accessing ** index files. */ setbuf( indexfp, NULL );#endif #ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) if((rc = LockIndex(F_SETLKW, F_WRLCK)) != 0) return rc;#endif /* parse the expression */ if(( rc = dbf->xbase->BuildExpressionTree( Exp, strlen( Exp ), dbf )) != XB_NO_ERROR ) return rc; ExpressionTree = dbf->xbase->GetTree(); dbf->xbase->SetTreeToNull(); /* build the header record */ memset( &HeadNode, 0x00, sizeof( NtxHeadNode )); HeadNode.Signature = 0x6; // Clipper 5.x HeadNode.Version = 1; HeadNode.StartNode = 1024L; KeyLen = CalcKeyLen(); // TODO // What is the Clipper key length limit? if( KeyLen == 0 || KeyLen > 100 ) /* 100 byte key length limit */ {#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif xb_error(XB_INVALID_KEY); } else { HeadNode.KeyLen = KeyLen; } // This is not the algorithm that Clipper uses. I cant figure out // what they use from looking at the examples. // This is correct tho. HeadNode.KeysPerNode = (xbUShort) (( XB_NTX_NODE_SIZE - (2 * sizeof( xbUShort ))) / (HeadNode.KeyLen + 10 )) - 1; if (HeadNode.KeysPerNode % 2) HeadNode.KeysPerNode--; HeadNode.HalfKeysPerNode = (xbUShort) HeadNode.KeysPerNode / 2; HeadNode.KeySize = HeadNode.KeyLen + 8;// while(( HeadNode.KeySize % 4 ) != 0 ) HeadNode.KeySize++; /* multiple of 4*/ HeadNode.Unique = Unique; strncpy( HeadNode.KeyExpression, Exp, 255 ); rc=AllocKeyBufs(); if(rc) { fclose(indexfp); return rc; }; if(( rc = PutHeadNode( &HeadNode, indexfp, 0 )) != 0 ) {#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif return rc; } /* write node #1 all 0x00 */ for( i = 0; i < XB_NTX_NODE_SIZE; i++ ) { if(( fwrite( "\x00", 1, 1, indexfp )) != 1 ) {#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif fclose( indexfp ); xb_io_error(XB_WRITE_ERROR, IndexName); } } IndexStatus = XB_OPEN; if ((rc = GetLeafNode(HeadNode.StartNode, 1)) != 0) {#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif return rc; } for (i = 0; i < HeadNode.KeysPerNode + 1; i++) { CurNode->offsets[i] = (i * HeadNode.KeySize) + 2 + (2 * (HeadNode.KeysPerNode + 1)); } if ((rc = PutLeafNode(HeadNode.StartNode, CurNode )) != 0) {#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif return rc; }#ifdef XB_LOCKING_ON if( dbf->GetAutoLock() ) LockIndex(F_SETLKW, F_UNLCK);#endif return dbf->AddIndexToIxList( index, IndexName ); }/***********************************************************************///! Short description./*! \param RecNo \param n \param NodeNo*/xbShort xbNtx::PutLeftNodeNo( xbShort RecNo, xbNodeLink *n, xbLong NodeNo ){ /* This routine sets n node's leftnode number */ NtxLeafNode *temp; char *p; xbUShort itemOffset; if( !n ) xb_error( XB_INVALID_NODELINK); temp = &n->Leaf; if( RecNo < 0 || RecNo > HeadNode.KeysPerNode) xb_error(XB_INVALID_KEY); p = temp->KeyRecs; itemOffset = GetItemOffset(RecNo, n, 1); p += itemOffset; dbf->xbase->PutLong( p, NodeNo ); return XB_NO_ERROR;}/***********************************************************************///! Short description./*! \param RecNo \param n \param DbfNo*/xbShort xbNtx::PutDbfNo( xbShort RecNo, xbNodeLink *n, xbLong DbfNo ){ /* This routine sets n node's dbf number */ NtxLeafNode *temp; char *p; xbUShort itemOffset; if( !n ) xb_error( XB_INVALID_NODELINK); temp = &n->Leaf; if( RecNo < 0 || RecNo > (HeadNode.KeysPerNode)) xb_error(XB_INVALID_KEY); itemOffset = GetItemOffset(RecNo, n, 1); p = temp->KeyRecs; p += itemOffset; p += 4; dbf->xbase->PutLong( p, DbfNo ); return XB_NO_ERROR;}/************************************************************************///! Short description./*! \param l \param n*/xbShort xbNtx::PutLeafNode( xbLong l, xbNodeLink *n ){ NtxLeafNode *temp; char *p; if(( fseek( indexfp, l , SEEK_SET )) != 0 ) { fclose( indexfp ); xb_io_error( XB_SEEK_ERROR, IndexName ); } temp = &n->Leaf; p = temp->KeyRecs; dbf->xbase->PutShort( p, temp->NoOfKeysThisNode ); // The offsets at the head of each leaf are not necessarly in order. p += 2; for (int i = 0; i < HeadNode.KeysPerNode + 1; i++) { dbf->xbase->PutShort( p, n->offsets[i] ); p += 2; } if(( fwrite( &n->Leaf.KeyRecs, XB_NTX_NODE_SIZE, 1, indexfp )) != 1 ) { fclose( indexfp ); xb_io_error(XB_WRITE_ERROR, IndexName); } PutHeadNode(&HeadNode, indexfp, 1); return 0; }/************************************************************************///! Short description./*! \param Head \param f \param UpdateOnly*/xbShort xbNtx::PutHeadNode( NtxHeadNode * Head, FILE * f, xbShort UpdateOnly ){ char buf[4]; char *p; if(( fseek( f, 0L, SEEK_SET )) != 0 ) { fclose( f ); xb_io_error( XB_SEEK_ERROR, IndexName ); } memset( buf, 0x00, 2 ); dbf->xbase->PutUShort( buf, Head->Signature ); if(( fwrite( &buf, 2, 1, f )) != 1 ) { fclose( f ); xb_io_error(XB_WRITE_ERROR, IndexName); } memset( buf, 0x00, 2 ); dbf->xbase->PutUShort( buf, Head->Version ); if(( fwrite( &buf, 2, 1, f )) != 1 ) { fclose( f ); xb_io_error( XB_WRITE_ERROR, IndexName ); } memset( buf, 0x00, 4 ); dbf->xbase->PutULong( buf, Head->StartNode ); if(( fwrite( &buf, 4, 1, f )) != 1 ) { fclose( f ); xb_io_error( XB_WRITE_ERROR, IndexName ); } memset( buf, 0x00, 4 ); dbf->xbase->PutULong( buf, Head->UnusedOffset ); if(( fwrite( &buf, 4, 1, f )) != 1 ) { fclose( f ); xb_io_error( XB_WRITE_ERROR, IndexName ); } if( UpdateOnly ) { fflush(indexfp); xb_io_error( XB_NO_ERROR, IndexName ); } memset( buf, 0x00, 2 ); dbf->xbase->PutUShort( buf, Head->KeySize ); if(( fwrite( &buf, 2, 1, f )) != 1 ) { fclose( f ); xb_io_error( XB_WRITE_ERROR, IndexName ); } memset( buf, 0x00, 2 ); dbf->xbase->PutUShort( buf, Head->KeyLen ); if(( fwrite( &buf, 2, 1, f )) != 1 ) { fclose( f ); xb_io_error( XB_WRITE_ERROR, IndexName ); } memset( buf, 0x00, 2 ); dbf->xbase->PutUShort( buf, Head->DecimalCount ); if(( fwrite( &buf, 2, 1, f )) != 1 ) { fclose( f ); xb_io_error( XB_WRITE_ERROR, IndexName ); } memset( buf, 0x00, 2 ); dbf->xbase->PutUShort( buf, Head->KeysPerNode ); if(( fwrite( &buf, 2, 1, f )) != 1 ) { fclose( f ); xb_io_error( XB_WRITE_ERROR, IndexName ); } memset( buf, 0x00, 2 ); dbf->xbase->PutUShort( buf, Head->HalfKeysPerNode ); if(( fwrite( &buf, 2, 1, f )) != 1 ) { fclose( f ); xb_io_error( XB_WRITE_ERROR, IndexName ); } p = HeadNode.KeyExpression; while (*p) { *p = tolower(*p); p++; } if(( fwrite( &Head->KeyExpression, 256, 1, f )) != 1 ) { fclose( f ); xb_io_error( XB_WRITE_ERROR, IndexName ); } memset( buf, 0x00, 1 ); buf[0] = Head->Unique; if(( fwrite( &buf, 1, 1, f )) != 1 ) { fclose( f ); xb_io_error( XB_WRITE_ERROR, IndexName ); } if(( fwrite( &Head->NotUsed, 745, 1, f )) != 1 ) { fclose( f ); xb_io_error( XB_WRITE_ERROR, IndexName ); } return 0; }xbShort xbNtx::TouchIndex( void ){ xbShort rc; if (( rc = GetHeadNode()) != XB_NO_ERROR) return rc; HeadNode.Version++; if (( rc = PutHeadNode(&HeadNode, indexfp, 1)) != XB_NO_ERROR) return rc; return XB_NO_ERROR;}/************************************************************************///! Short description./*! \param RecNo \param n*/xbShort xbNtx::PutKeyData( xbShort RecNo, xbNodeLink *n ){ /* This routine copies the KeyBuf data into xbNodeLink n */ NtxLeafNode *temp; char *p; xbShort i; xbUShort itemOffset; if( !n ) xb_error( XB_INVALID_NODELINK ); temp = &n->Leaf; if( RecNo < 0 || RecNo > (HeadNode.KeysPerNode)) xb_error( XB_INVALID_KEY ); itemOffset = GetItemOffset(RecNo, n, 1); p = temp->KeyRecs; p += itemOffset; p += 8; for( i = 0; i < HeadNode.KeyLen; i++ ) { *p = KeyBuf[i]; p++; } return XB_NO_ERROR;}/************************************************************************///! Short description./*! \param n \param pos \param d \param l \param w*/xbShort xbNtx::PutKeyInNode( xbNodeLink * n, xbShort pos, xbLong d, xbLong l, xbShort w ){ /* check the node */ if( !n ) xb_error( XB_INVALID_NODELINK ); if( pos < 0 || pos > HeadNode.KeysPerNode ) xb_error( XB_INVALID_RECORD ); if( n->Leaf.NoOfKeysThisNode >= HeadNode.KeysPerNode ) xb_error( XB_NODE_FULL ); InsertKeyOffset(pos, n); PutKeyData( pos, n ); PutDbfNo( pos, n, d ); PutLeftNodeNo( pos, n, l ); n->Leaf.NoOfKeysThisNode++; if( w ) return PutLeafNode( n->NodeNo, n ); else return 0;}/************************************************************************///! Short description./*! \param n1 \param n2 \param pos \param d*/xbShort xbNtx::SplitLeafNode( xbNodeLink *n1, xbNodeLink *n2, xbShort pos, xbLong d ){ xbShort i,j,rc; xbShort temp; xbShort start; xbShort end; xbShort length; if( !n1 || !n2 ) xb_error( XB_INVALID_NODELINK ); if( pos < 0 || pos > HeadNode.KeysPerNode ) xb_error( XB_INVALID_RECORD ); length = strlen(KeyBuf); // If the new key goes in the first node. if (pos < HeadNode.HalfKeysPerNode) { // Setup key to insert into parent memcpy(PushItem.Key, GetKeyData(HeadNode.HalfKeysPerNode -1, n1), HeadNode.KeyLen); PushItem.RecordNumber = GetDbfNo(HeadNode.HalfKeysPerNode -1, n1); PushItem.Node = 0L; start = pos; end = HeadNode.HalfKeysPerNode - 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -