324 lines
6.9 KiB
C
324 lines
6.9 KiB
C
|
/* AMX Mod X
|
||
|
*
|
||
|
* by the AMX Mod X Development Team
|
||
|
* originally developed by OLO
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify it
|
||
|
* under the terms of the GNU General Public License as published by the
|
||
|
* Free Software Foundation; either version 2 of the License, or (at
|
||
|
* your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software Foundation,
|
||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
*
|
||
|
* In addition, as a special exception, the author gives permission to
|
||
|
* link the code of this program with the Half-Life Game Engine ("HL
|
||
|
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||
|
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||
|
* respects for all of the code used other than the HL Engine and MODs
|
||
|
* from Valve. If you modify this file, you may extend this exception
|
||
|
* to your version of the file, but you are not obligated to do so. If
|
||
|
* you do not wish to do so, delete this exception statement from your
|
||
|
* version.
|
||
|
*/
|
||
|
|
||
|
#ifndef DATASTRUCTS_H
|
||
|
#define DATASTRUCTS_H
|
||
|
|
||
|
class CellVector
|
||
|
{
|
||
|
private:
|
||
|
cell* data; // allocated with malloc
|
||
|
size_t cellcount; // how many cells per element
|
||
|
size_t cursize; // current size of the vector (maximum elements)
|
||
|
size_t count; // how many units of the vector are in use
|
||
|
|
||
|
public:
|
||
|
CellVector(): data(NULL), cellcount(0), cursize(0), count(0)
|
||
|
{
|
||
|
};
|
||
|
CellVector(int cellsize): data(NULL), cellcount(cellsize), cursize(0), count(0)
|
||
|
{
|
||
|
};
|
||
|
~CellVector()
|
||
|
{
|
||
|
if (data)
|
||
|
{
|
||
|
free(data);
|
||
|
}
|
||
|
};
|
||
|
size_t GetCellCount()
|
||
|
{
|
||
|
return cellcount;
|
||
|
};
|
||
|
void Grow(size_t howmany)
|
||
|
{
|
||
|
cursize+=howmany;
|
||
|
if (data)
|
||
|
{
|
||
|
data=(cell*)realloc(data, (sizeof(cell) * cellcount) * cursize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
data=(cell*)malloc((sizeof(cell) * cellcount) * cursize);
|
||
|
}
|
||
|
};
|
||
|
void FreeUnused(void)
|
||
|
{
|
||
|
if (cursize != count &&
|
||
|
data != NULL)
|
||
|
{
|
||
|
cursize=count;
|
||
|
data=(cell*)realloc(data, cursize * (sizeof(cell) * cellcount));
|
||
|
}
|
||
|
};
|
||
|
// Returns 1 on success
|
||
|
// 0 on out of bounds.
|
||
|
int GetArray(size_t which, cell* output)
|
||
|
{
|
||
|
// make sure it is in bounds.
|
||
|
if (which >= count)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
// align output data
|
||
|
cell* out=data + (cellcount * which);
|
||
|
|
||
|
memcpy(output, out, sizeof(cell) * cellcount);
|
||
|
|
||
|
return 1;
|
||
|
};
|
||
|
// Returns 1 on success
|
||
|
// 0 on out of bounds
|
||
|
int GetCell(size_t which, cell* output)
|
||
|
{
|
||
|
// check bounds
|
||
|
if (which >= count)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
*output=*(data + (cellcount * which));
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
// Returns 1 on success
|
||
|
// 0 on out of bounds
|
||
|
int GetString(size_t which, cell* output, size_t size)
|
||
|
{
|
||
|
// check bounds
|
||
|
if (which >= count)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
cell* out=data + (cellcount * which);
|
||
|
|
||
|
size_t count=cellcount;
|
||
|
|
||
|
while (size-- &&
|
||
|
count-- &&
|
||
|
(*output++=*out++)!='\0')
|
||
|
/* do nothing */ ;
|
||
|
|
||
|
// If size is zero here, then the string was never null terminated.
|
||
|
if (size==0)
|
||
|
{
|
||
|
*out='\0';
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
// Returns 1 on success
|
||
|
// 0 on out of bounds
|
||
|
int SetArray(size_t which, cell* output)
|
||
|
{
|
||
|
if (which >= count)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
// align output
|
||
|
cell* out=data + (cellcount * which);
|
||
|
|
||
|
memcpy(out, output, sizeof(cell) * cellcount);
|
||
|
|
||
|
return 1;
|
||
|
};
|
||
|
// Returns 1 on success
|
||
|
// 0 on out of bounds
|
||
|
int SetCell(size_t which, cell output)
|
||
|
{
|
||
|
if (which >= count)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
// align output
|
||
|
*(data + (cellcount * which))=output;
|
||
|
|
||
|
return 1;
|
||
|
};
|
||
|
// Returns 1 on success
|
||
|
// 0 on out of bounds
|
||
|
int SetString(size_t which, cell* output)
|
||
|
{
|
||
|
if (which >= count)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
// align output
|
||
|
cell* out=data + (cellcount * which);
|
||
|
|
||
|
memcpy(out, output, sizeof(cell) * cellcount);
|
||
|
|
||
|
// now force a null terminator on the last entry.
|
||
|
out+=(cellcount - 1);
|
||
|
*out='\0';
|
||
|
|
||
|
return 1;
|
||
|
};
|
||
|
int Push()
|
||
|
{
|
||
|
if (count >= cursize)
|
||
|
{
|
||
|
// Grow in 8s to cause less reallocation
|
||
|
this->Grow(8);
|
||
|
};
|
||
|
|
||
|
this->count++;
|
||
|
|
||
|
return this->count-1;
|
||
|
};
|
||
|
int Size()
|
||
|
{
|
||
|
return this->count;
|
||
|
};
|
||
|
void Clear()
|
||
|
{
|
||
|
free(data);
|
||
|
data=(cell*)malloc(sizeof(cell) * cellcount);
|
||
|
cursize=1;
|
||
|
count=0;
|
||
|
};
|
||
|
cell* GetCellPointer(size_t which)
|
||
|
{
|
||
|
if (which >= count)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
return data + (which * cellcount);
|
||
|
};
|
||
|
// Shifts all items from this item, and including this item up 1.
|
||
|
int ShiftUpFrom(size_t which)
|
||
|
{
|
||
|
// No point shifting this.
|
||
|
if (this->count < 0 ||
|
||
|
which > this->count)
|
||
|
{
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
// First make a new item.
|
||
|
this->Push();
|
||
|
|
||
|
// If we got an InsertAfter(lastitem), then which will equal this->count - 1
|
||
|
// all we needed to do was Push()
|
||
|
if (which == this->count ||
|
||
|
which == this->count - 1)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// Allocate a temporary buffer to store data in
|
||
|
size_t tempbuffsize=(sizeof(cell) * cellcount) * (this->count - which);
|
||
|
|
||
|
cell* temp=(cell*)malloc(tempbuffsize);
|
||
|
|
||
|
// Copy old data to temp buffer
|
||
|
memcpy(temp, GetCellPointer(which), tempbuffsize);
|
||
|
|
||
|
// Now copy temp buffer to adjusted location
|
||
|
memcpy(GetCellPointer(which+1), temp, tempbuffsize);
|
||
|
|
||
|
// cleanup
|
||
|
free(temp);
|
||
|
|
||
|
return 1;
|
||
|
|
||
|
};
|
||
|
// Shifts all items from this item, and including this item down 1.
|
||
|
// This deletes the item specified.
|
||
|
int Delete(size_t which)
|
||
|
{
|
||
|
// No point shifting this.
|
||
|
if (this->count < 0 ||
|
||
|
which >= this->count)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
for (size_t i=which; i<this->count - 1; i++)
|
||
|
{
|
||
|
memcpy(GetCellPointer(i), GetCellPointer(i + 1), sizeof(cell) * cellcount);
|
||
|
}
|
||
|
this->count--;
|
||
|
return 1;
|
||
|
};
|
||
|
int Swap(size_t item1, size_t item2)
|
||
|
{
|
||
|
if (item1 >= this->count ||
|
||
|
item2 >= this->count)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Make a temp buffer to store item2
|
||
|
cell* temp=(cell*)malloc(sizeof(cell) * cellcount);
|
||
|
memcpy(temp, GetCellPointer(item2), sizeof(cell) * cellcount);
|
||
|
|
||
|
// copy item1 to item2
|
||
|
memcpy(GetCellPointer(item2), GetCellPointer(item1), sizeof(cell) * cellcount);
|
||
|
|
||
|
// copy item2 to item1
|
||
|
memcpy(GetCellPointer(item1), temp, sizeof(cell) * cellcount);
|
||
|
|
||
|
// Cleanup
|
||
|
free(temp);
|
||
|
|
||
|
return 1;
|
||
|
};
|
||
|
|
||
|
};
|
||
|
|
||
|
extern CVector<CellVector*> VectorHolder;
|
||
|
|
||
|
|
||
|
inline CellVector* HandleToVector(AMX* amx, int handle)
|
||
|
{
|
||
|
if (handle <= 0 ||
|
||
|
handle > (int)VectorHolder.size())
|
||
|
{
|
||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", handle);
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
CellVector* ret=VectorHolder[handle-1];
|
||
|
|
||
|
if (ret == NULL)
|
||
|
{
|
||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", handle);
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif
|