core/smn_core.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jun 06 16:40:30 2007 +0000 (2007-06-06)
changeset 886 649c859c2272
parent 837 de0223664adc
child 889 176ae94f3747
permissions -rw-r--r--
added GetSysTickCount for benchmarking
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * ===============================================================
     6  *
     7  * This file is not open source and may not be copied without explicit
     8  * written permission of AlliedModders LLC.  This file may not be redistributed 
     9  * in whole or significant part.
    10  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    11  *
    12  * Version: $Id$
    13  */
    14 
    15 #include <time.h>
    16 #include "sm_globals.h"
    17 #include "sourcemod.h"
    18 #include "PluginSys.h"
    19 #include "HandleSys.h"
    20 
    21 #if defined PLATFORM_WINDOWS
    22 #include <windows.h>
    23 #elif defined PLATFORM_LINUX
    24 #include <limits.h>
    25 #include <unistd.h>
    26 #include <sys/times.h>
    27 #endif
    28 
    29 HandleType_t g_PlIter;
    30 
    31 class CoreNativeHelpers : 
    32 	public SMGlobalClass,
    33 	public IHandleTypeDispatch
    34 {
    35 public:
    36 	void OnSourceModAllInitialized()
    37 	{
    38 		HandleAccess hacc;
    39 		g_HandleSys.InitAccessDefaults(NULL,  &hacc);
    40 		hacc.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
    41 
    42 		g_PlIter = g_HandleSys.CreateType("PluginIterator", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    43 	}
    44 	void OnHandleDestroy(HandleType_t type, void *object)
    45 	{
    46 		IPluginIterator *iter = (IPluginIterator *)object;
    47 		iter->Release();
    48 	}
    49 	void OnSourceModShutdown()
    50 	{
    51 		g_HandleSys.RemoveType(g_PlIter, g_pCoreIdent);
    52 	}
    53 } g_CoreNativeHelpers;
    54 
    55 
    56 static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
    57 {
    58 	char buffer[512];
    59 
    60 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
    61 
    62 	if (pContext->GetContext()->n_err == SP_ERROR_NONE)
    63 	{
    64 		pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
    65 	}
    66 
    67 	return 0;
    68 }
    69 
    70 static cell_t GetTime(IPluginContext *pContext, const cell_t *params)
    71 {
    72 	time_t t = time(NULL);
    73 	cell_t *addr;
    74 	pContext->LocalToPhysAddr(params[1], &addr);
    75 
    76 	*(time_t *)addr = t;
    77 
    78 	return static_cast<cell_t>(t);
    79 }
    80 
    81 static cell_t GetPluginIterator(IPluginContext *pContext, const cell_t *params)
    82 {
    83 	IPluginIterator *iter = g_PluginSys.GetPluginIterator();
    84 
    85 	Handle_t hndl = g_HandleSys.CreateHandle(g_PlIter, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
    86 
    87 	if (hndl == BAD_HANDLE)
    88 	{
    89 		iter->Release();
    90 	}
    91 
    92 	return hndl;
    93 }
    94 
    95 static cell_t MorePlugins(IPluginContext *pContext, const cell_t *params)
    96 {
    97 	Handle_t hndl = (Handle_t)params[1];
    98 	HandleError err;
    99 	IPluginIterator *pIter;
   100 
   101 	HandleSecurity sec;
   102 	sec.pIdentity = g_pCoreIdent;
   103 	sec.pOwner = pContext->GetIdentity();
   104 
   105 	if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
   106 	{
   107 		return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
   108 	}
   109 
   110 	return pIter->MorePlugins() ? 1 : 0;
   111 }
   112 
   113 static cell_t ReadPlugin(IPluginContext *pContext, const cell_t *params)
   114 {
   115 	Handle_t hndl = (Handle_t)params[1];
   116 	HandleError err;
   117 	IPluginIterator *pIter;
   118 
   119 	HandleSecurity sec;
   120 	sec.pIdentity = g_pCoreIdent;
   121 	sec.pOwner = pContext->GetIdentity();
   122 
   123 	if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
   124 	{
   125 		return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
   126 	}
   127 
   128 	CPlugin *pPlugin = (CPlugin *)pIter->GetPlugin();
   129 	if (!pPlugin)
   130 	{
   131 		return BAD_HANDLE;
   132 	}
   133 
   134 	pIter->NextPlugin();
   135 
   136 	return pPlugin->GetMyHandle();
   137 }
   138 
   139 CPlugin *GetPluginFromHandle(IPluginContext *pContext, Handle_t hndl)
   140 {
   141 	if (hndl == BAD_HANDLE)
   142 	{
   143 		return g_PluginSys.GetPluginByCtx(pContext->GetContext());
   144 	} else {
   145 		HandleError err;
   146 		CPlugin *pPlugin = (CPlugin *)g_PluginSys.PluginFromHandle(hndl, &err);
   147 		if (!pPlugin)
   148 		{
   149 			pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
   150 		}
   151 		return pPlugin;
   152 	}
   153 }
   154 
   155 static cell_t GetPluginStatus(IPluginContext *pContext, const cell_t *params)
   156 {
   157 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   158 	if (!pPlugin)
   159 	{
   160 		return 0;
   161 	}
   162 
   163 	return pPlugin->GetStatus();
   164 }
   165 
   166 static cell_t GetPluginFilename(IPluginContext *pContext, const cell_t *params)
   167 {
   168 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   169 	if (!pPlugin)
   170 	{
   171 		return 0;
   172 	}
   173 
   174 	pContext->StringToLocalUTF8(params[2], params[3], pPlugin->GetFilename(), NULL);
   175 
   176 	return 1;
   177 }
   178 
   179 static cell_t IsPluginDebugging(IPluginContext *pContext, const cell_t *params)
   180 {
   181 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   182 	if (!pPlugin)
   183 	{
   184 		return 0;
   185 	}
   186 
   187 	return pPlugin->IsDebugging() ? 1 : 0;
   188 }
   189 
   190 /* Local to plugins only */
   191 enum PluginInfo
   192 {
   193 	PlInfo_Name,			/**< Plugin name */
   194 	PlInfo_Author,			/**< Plugin author */
   195 	PlInfo_Description,		/**< Plugin description */
   196 	PlInfo_Version,			/**< Plugin verison */
   197 	PlInfo_URL,				/**< Plugin URL */
   198 };
   199 
   200 static cell_t GetPluginInfo(IPluginContext *pContext, const cell_t *params)
   201 {
   202 	CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
   203 	if (!pPlugin)
   204 	{
   205 		return 0;
   206 	}
   207 
   208 	const sm_plugininfo_t *info = pPlugin->GetPublicInfo();
   209 
   210 	if (!info)
   211 	{
   212 		return 0;
   213 	}
   214 
   215 	const char *str = NULL;
   216 
   217 	switch ((PluginInfo)params[2])
   218 	{
   219 	case PlInfo_Name:
   220 		{
   221 			str = info->name;
   222 			break;
   223 		}
   224 	case PlInfo_Author:
   225 		{
   226 			str = info->author;
   227 			break;
   228 		}
   229 	case PlInfo_Description:
   230 		{
   231 			str = info->description;
   232 			break;
   233 		}
   234 	case PlInfo_Version:
   235 		{
   236 			str = info->version;
   237 			break;
   238 		}
   239 	case PlInfo_URL:
   240 		{
   241 			str = info->url;
   242 			break;
   243 		}
   244 	}
   245 
   246 	if (!str || str[0] == '\0')
   247 	{
   248 		return 0;
   249 	}
   250 
   251 	pContext->StringToLocalUTF8(params[3], params[4], str, NULL);
   252 
   253 	return 1;
   254 }
   255 
   256 static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
   257 {
   258 	char *str;
   259 	pContext->LocalToString(params[1], &str);
   260 
   261 	CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
   262 	pPlugin->SetErrorState(Plugin_Error, "%s", str);
   263 
   264 	return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", str);
   265 }
   266 
   267 static cell_t GetSysTickCount(IPluginContext *pContext, const cell_t *params)
   268 {
   269 #if defined PLATFORM_WINDOWS
   270 	return (cell_t)GetTickCount();
   271 #elif defined PLATFORM_LINUX
   272 	tms tm;
   273 	clock_t ticks = times(&tm);
   274 	long ticks_per_sec = sysconf(_SC_CLK_TCK);
   275 	double ftcks = (double)ticks / (double)ticks_per_sec;
   276 	fticks *= 1000.0f;
   277 	if (fticks > INT_MAX)
   278 	{
   279 		double r = (int)(fticks / INT_MAX) * (double)INT_MAX;
   280 		fticks -= r;
   281 	}
   282 	return (cell_t)fticks;
   283 #endif
   284 }
   285 
   286 REGISTER_NATIVES(coreNatives)
   287 {
   288 	{"GetPluginFilename",	GetPluginFilename},
   289 	{"GetPluginInfo",		GetPluginInfo},
   290 	{"GetPluginIterator",	GetPluginIterator},
   291 	{"GetPluginStatus",		GetPluginStatus},
   292 	{"GetSysTickCount",		GetSysTickCount},
   293 	{"GetTime",				GetTime},
   294 	{"IsPluginDebugging",	IsPluginDebugging},
   295 	{"MorePlugins",			MorePlugins},
   296 	{"ReadPlugin",			ReadPlugin},
   297 	{"ThrowError",			ThrowError},
   298 	{"SetFailState",		SetFailState},
   299 	{NULL,					NULL},
   300 };