📄 stl.hhf
字号:
////////////////////////////////////////////////////////////////////////////////// Container-//// All container objects are a subclass of "Container"type Container: class inherits( base ); val hierarchy_c := hierarchy_c | isContainer_c; var align(4); // # of elements (nodes, whatever) in the container numElements :uns32; // For containers (i.e., the isContainer_c bit is set in // capabilities), containerName specifies the name of // the container (e.g., "vector") containerName :string; method getSize; @returns( "eax" ); endclass; // getSize- // Returns the number of container items in EAX: method Container.getSize; @noframe; begin getSize; mov( this.numElements, eax ); ret(); end getSize;static vmt(Container);//////////////////////////////////////////////////////////////////////////////// RandomAccessContainer-// All Random Access class objects are a subclass of RandomAccessContainer:type RandomAccessContainer: class inherits( Container ); val hierarchy_c := hierarchy_c | isRandomAccess_c; endclass;//////////////////////////////////////////////////////////////////////////////// ArrayContainer-// All Array class objects are a subclass of ArrayContainer:type ArrayContainer: class inherits( RandomAccessContainer ); val hierarchy_c := hierarchy_c | isArray_c; var align( 4 ); // Pointer to allocated storage: allocData :dword; // Pointer to end of allocated storage endAllocData :dword; // Max space for current allocation allocSize :uns32; // Pointer to start of array data: data :dword; // Pointer to end of array data: endData :dword; // Size of array data currently in use dataSize :uns32; method getAllocSize; @returns( "eax" ); method getDataSize; @returns( "eax" ); method createArray( n:uns32; elementSize:uns32 ); method clear; method destroy; endclass; method ArrayContainer.getAllocSize; @noframe; begin getAllocSize; mov( this.allocSize, eax ); ret(); end getAllocSize; method ArrayContainer.getDataSize; @noframe; begin getDataSize; mov( this.dataSize, eax ); ret(); end getDataSize; // Create a generic array object // (this is a private routine for use by derivative classes) method ArrayContainer.createArray( n:uns32; elementSize:uns32 ); @nodisplay; @nostackalign; begin createArray; push( eax ); // Allocate storage for the array and initialize // the appropriate fields: mov( 0, this.numElements ); // No actual elements in use yet. mov( 0, this.dataSize ); mov( n, eax ); intmul( elementSize, eax ); mov( eax, this.allocSize ); // Allocated size for vector. @global:mem.alloc( eax ); mov( eax, this.allocData ); // Pointer to allocated data. mov( eax, this.data ); mov( eax, this.endData ); // Empty vector, endData is same as data add( this.allocSize, eax ); // Compute endAllocData mov( eax, this.endAllocData ); pop( eax ); end createArray; // Destroy- // This is the generic destructor for array types. method ArrayContainer.destroy; @noframe; begin destroy; @global:mem.free( this.allocData ); // Free the data storage xor( eax, eax ); mov( eax, this.allocData ); mov( eax, this.endAllocData ); mov( eax, this.data ); mov( eax, this.endData ); mov( eax, this.allocSize ); mov( eax, this.numElements ); mov( eax, this.dataSize ); if( this.isAlloc ) then // If object was created on the heap, free it here: @global:mem.free( esi ); endif; ret(); end destroy; // Clear- // Clears (but does not deallocate storage) all the elements // in the array. method ArrayContainer.clear; @noframe; begin clear; push( eax ); mov( 0, this.numElements ); mov( 0, this.dataSize ); mov( this.data, eax ); mov( eax, this.endData ); pop( eax ); ret(); end clear; static vmt( ArrayContainer ); ////////////////////////////////////////////////////////////////////////////////// _vector// This is a special "helper" class for the vector template that moves a lot// of code common to all vector types into a single class in order to reduce// the size of the code base produced by expanding a vector template. No// program should actually declare variables of type _vector, this class is// for internal use only.type _vector: class inherits( ArrayContainer ); procedure _append( toAppend:dword; appendSize:dword ); @use eax; procedure _insert ( toInsert:dword; insertWhere:dword; insertSize:dword ); procedure _remove( removeWhere:dword; removeSize:dword ); endclass; // _append- // Appends a new element to the end of the vector. // // Inputs: // // toAppend- // Pointer to the data to append to the vector // // appendSize- // Size of the data object to append. procedure _vector._append( toAppend:dword; appendSize:dword ); @nodisplay; @noalignstack; readonly sixteenCases:dword[17] := [ &defaultCase, &case1, &case2, &defaultCase, &case4, &defaultCase, &defaultCase, &defaultCase, &case8, &defaultCase, &defaultCase, &defaultCase, &defaultCase, &defaultCase, &defaultCase, &defaultCase, &case16 ]; begin _append; // Begin by making sure we've got enough room in the // data array to hold the new object: mov( this.dataSize, edi ); add( appendSize, edi ); if( edi >= this.allocSize ) then // If the new element we're adding pushes us // beyond the end of the allocated storage, // reallocate by doubling the storage. shl( 1, edi ); mov( edi, this.allocSize ); @global:mem.realloc( this.allocData, edi ); mov( eax, this.data ); mov( eax, this.allocData ); add( eax, edi ); mov( edi, this.endAllocData ); endif; // Special case out various small object sizes // for performance reasons. mov( appendSize, ecx ); mov( this.data, edi ); add( this.dataSize, edi ); push( esi ); mov( toAppend, esi ); cld(); cmp( ecx, 16 ); ja defaultCase; jmp( sixteenCases[ ecx*4 ]); case1: movsb(); jmp caseDone; case2: movsw(); jmp caseDone; case4: movsd(); jmp caseDone; case8: movsd(); movsd(); jmp caseDone; case16: movsd(); movsd(); movsd(); movsd(); jmp caseDone; defaultCase: rep.movsb(); caseDone: pop( esi ); mov( edi, this.endData ); // Maintain ptr to end of data. // Okay, bump up the element count by one: add( 1, this.numElements ); mov( appendSize, eax ); add(eax, this.dataSize ); end _append; // _insert- // Inserts an arbitrary "vector" object into a vector. // // Inputs: // // toInsert- // Pointer to vector element to insert into the list. // // insertWhere- // Pointer to the spot in the vector where the new element // is to be inserted. // // insertSize- // Size of the object being inserted. procedure _vector._insert ( toInsert:dword; insertWhere:dword; insertSize:dword ); begin _insert; push( esi ); // As we're expanding the array by one element, let's make // sure we have room for the expansion: mov( this.dataSize, ecx ); add( insertSize, ecx ); if( ecx >= this.allocSize ) then // If the new element we're adding pushes us // beyond the end of the allocated storage, // reallocate by doubling the storage. lea( ecx, [ecx+ecx] ); mov( ecx, this.allocSize ); @global:mem.realloc( this.allocData, ecx ); mov( eax, this.data ); mov( eax, this.allocData ); add( ecx, eax ); mov( eax, this.endAllocData ); sub( ecx, eax ); add( this.dataSize, eax ); mov( eax, this.endData ); endif; // Okay, make room for the item we're going to insert: mov( insertWhere, eax ); if( eax >= this.endData ) then mov( this.endData, eax ); else // If we are inserting data at some point other than // at the end of the array, then we've got to move // everything along by one position to open up space // for the new element: std(); mov( this.endData, edi ); mov( edi, ecx ); sub( eax, ecx ); // Three variants of the actual insertion code, // based on the size of the object we're inserting: test( %11, insertSize ); jz do4; test( %1, insertSize ); jz do2; lea( esi, [edi-1] ); add( insertSize, edi ); sub( 1, edi ); rep.movsb(); jmp SpaceMade; do2: // Do this if the object's size is a multiple of 2 bytes: lea( esi, [edi-2] ); add( insertSize, edi ); sub( 2, edi ); shr( 1, ecx ); rep.movsw(); jmp SpaceMade; do4: lea( esi, [edi-4] ); add( insertSize, edi ); sub( 4, edi ); shr( 2, ecx ); rep.movsd(); SpaceMade: endif; // Okay, copy the data passed in toInsert into // the spot we've opened up: // // Three variants of the actual copy code, // based on the size of the object we're inserting: test( %11, insertSize ); jz do4a; test( %1, insertSize ); jz do2a; // Okay, copy the data passed in the toInsert // parameter into the location we've emptied up: cld(); mov( insertSize, ecx ); mov( toInsert, esi ); mov( eax, edi ); rep.movsb(); jmp copyDone; do2a: // Do this if the object's size is a multiple of 2 bytes: cld(); mov( insertSize, ecx ); mov( toInsert, esi ); shr( 1, ecx ); mov( eax, edi ); rep.movsw(); jmp copyDone; do4a: // Okay, copy the data passed in the toInsert // parameter into the location we've emptied up: cld(); mov( insertSize, ecx ); mov( toInsert, esi ); shr( 2, ecx ); mov( eax, edi ); rep.movsd(); copyDone: pop( esi ); // Update the endData pointer to reflect the new // array size: mov( insertSize, eax ); add( eax, this.endData ); add( eax, this.dataSize ); // We're one element larger, so take that into // consideration: add( 1, this.numElements ); end _insert; // _remove // Helper routine that removes a vector element from a vector. // // Inputs: // // removeWhere- // Address of element to remove. // // removeSize- // Size of element to remove. procedure _vector._remove( removeWhere:dword; removeSize:dword ); begin _remove; mov( removeWhere, eax ); if( eax < this.endData ) then push( ecx ); push( edi ); push( esi ); mov( this.endData, ecx ); sub( eax, ecx ); mov( eax, esi ); add( removeSize, esi ); mov( eax, edi ); // Special cases for vectorTypes whoses sizes // are multiples of two or four bytes: mov( removeSize, eax ); test( %11, eax ); jz do4; test( %1, eax ); jz do2; rep.movsb(); jmp RemoveDone; do2: shr( 1, ecx ); rep.movsw(); jmp RemoveDone; do4: shr( 2, ecx ); rep.movsd(); RemoveDone: pop( esi ); pop( edi ); pop( ecx ); sub( 1, this.numElements ); sub( eax, this.dataSize ); sub( eax, this.endData ); endif; end _remove;////////////////////////////////////////////////////////////////////////////////// The vector type.//// This is a dynamic array (single dimension) whose size can change// as needed at runtime.//// Arguments://// vectorType-// data type for each element in the vector//// specificCapabilities-// Enabled/disabled capabilities for this vector (used to alter// the default settings for a vector).////// Produces://// Three different types://// vectorType-// a class for the specified vector type.//// vectorType_cursor-// a type for cursors that point into the vectorType class.//// p_vectorType-// a pointer to the vectorType class.//// (Note: substitute the actual parameter name for "vectorType"// in each of the above)//// Publically accessible fields in the class created by this macro// (these fields should be treated as read-only):// // isSTL_c-// a constant, set to true, that you can use @define on to// determine that this type is an STL type.//// capabilities_c (compile-time)// capabilities (run-time)// a bit-mapped array of booleans that specify the capabilities of// a vector object. Test for the presence of a capability by ANDing// with one of the *_c constants.//// typeName-// a string holding the vectorType type name.//// containerName-// the string "vector".////// procedures, methods, and iterators://// procedure create( numElements:uns32 );// Constructor for the vector class. If called with the class// name (e.g., symbol.create(n)) then it will create the object// on the heap and return a pointer to the new "symbol" object// in the ESI register. If called with an actual "symbol" variable,// this constructor initializes that variable.//// Note: if the underlying vector type is a class type, this// constructor does *not* call the create procedure for each// of the underlying elements in the vector. That is the caller's// responsibility.//// method destroy;// Destructor for the vector template class. Deallocates the storage// associated with the object. Note that if the underlying elements// are a class type, this destructor does not call the destructor// for each of those elements. You must explicitly destroy them// prior to calling this destructor.//// method getSize;// returns the number of vector elements in EAX. Operates in O(1) time.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -