extensions/regex/extension.cpp
author Scott Ehlert <ds@alliedmods.net>
Sun Sep 14 03:01:05 2008 -0500 (2008-09-14)
changeset 2289 44045ead61cd
parent 1990 de135d1f05b1
parent 1947 e73a1e51833b
child 2783 5f333027ef04
permissions -rw-r--r--
Eliminated head: da55a80522cf, a remnant of sourcemod-1.1.0 branch
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod Regular Expressions Extension
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "extension.h"
    33 
    34 #include <sh_string.h>
    35 #include "pcre.h"
    36 #include "CRegEx.h"
    37 using namespace SourceHook;
    38 
    39 /**
    40  * @file extension.cpp
    41  * @brief Implement Regex extension code here.
    42  */
    43 
    44 RegexExtension g_RegexExtension;		/**< Global singleton for extension's main interface */
    45 
    46 SMEXT_LINK(&g_RegexExtension);
    47 
    48 RegexHandler g_RegexHandler;
    49 HandleType_t g_RegexHandle=0;
    50 
    51 
    52 
    53 bool RegexExtension::SDK_OnLoad(char *error, size_t err_max, bool late)
    54 {
    55 	g_pShareSys->AddNatives(myself,regex_natives);
    56 	g_RegexHandle = g_pHandleSys->CreateType("Regex", &g_RegexHandler, 0, NULL, NULL, myself->GetIdentity(), NULL);
    57 	return true;
    58 }
    59 
    60 void RegexExtension::SDK_OnUnload()
    61 {
    62 	g_pHandleSys->RemoveType(g_RegexHandle, myself->GetIdentity());
    63 
    64 }
    65 
    66 static cell_t CompileRegex(IPluginContext *pCtx, const cell_t *params)
    67 {
    68 	char *regex;
    69 	pCtx->LocalToString(params[1], &regex);
    70 
    71 	RegEx *x = new RegEx();
    72 	
    73 	if (x->Compile(regex, params[2]) == 0)
    74 	{
    75 		cell_t *eOff;
    76 		pCtx->LocalToPhysAddr(params[5], &eOff);
    77 		const char *err = x->mError;
    78 		*eOff = x->mErrorOffset;
    79 		pCtx->StringToLocal(params[3], params[4], err ? err:"unknown");
    80 		return 0;
    81 	}
    82 
    83 	return g_pHandleSys->CreateHandle(g_RegexHandle, (void*)x, pCtx->GetIdentity(), myself->GetIdentity(), NULL);
    84 }
    85 
    86 
    87 static cell_t MatchRegex(IPluginContext *pCtx, const cell_t *params)
    88 {
    89 	Handle_t hndl = static_cast<Handle_t>(params[1]);
    90 	HandleError err;
    91 	HandleSecurity sec;
    92 	sec.pOwner = NULL;
    93 	sec.pIdentity = myself->GetIdentity();
    94 
    95 	RegEx *x;
    96 
    97 	if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
    98 	{
    99 		return pCtx->ThrowNativeError("Invalid file handle %x (error %d)", hndl, err);
   100 	}
   101 
   102 	if (!x)
   103 	{
   104 		pCtx->ThrowNativeError("Regex data not found\n");
   105 
   106 		return 0;
   107 	}
   108 
   109 	char *str;
   110 	pCtx->LocalToString(params[2], &str);
   111 
   112 	int e = x->Match(str);
   113 
   114 	if (e == -1)
   115 	{
   116 		/* there was a match error.  move on. */
   117 		cell_t *res;
   118 		pCtx->LocalToPhysAddr(params[3], &res);
   119 		*res = x->mErrorOffset;
   120 		/* only clear the match results, since the regex object
   121 		   may still be referenced later */
   122 		x->ClearMatch();
   123 
   124 		return -1;
   125 	}
   126 	else if (e == 0) 
   127 	{
   128 		/* only clear the match results, since the regex object
   129 		   may still be referenced later */
   130 		x->ClearMatch();
   131 
   132 		return 0;
   133 	} 
   134 	else 
   135 	{
   136 		return x->mSubStrings;
   137 	}
   138 }
   139 
   140 static cell_t GetRegexSubString(IPluginContext *pCtx, const cell_t *params)
   141 {
   142 	Handle_t hndl=static_cast<Handle_t>(params[1]);
   143 	HandleError err;
   144 	HandleSecurity sec;
   145 	sec.pOwner=NULL;
   146 	sec.pIdentity=myself->GetIdentity();
   147 
   148 	RegEx *x;
   149 
   150 	if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
   151 	{
   152 		return pCtx->ThrowNativeError("Invalid file handle %x (error %d)", hndl, err);
   153 	}
   154 
   155 	if (!x)
   156 	{
   157 		pCtx->ThrowNativeError("Regex data not found\n");
   158 		return 0;
   159 	}
   160 
   161 	static char buffer[4096];
   162 	const char *ret=x->GetSubstring(params[2], buffer, sizeof(buffer));
   163 
   164 	if(!ret)
   165 	{
   166 		return 0;
   167 	}
   168 
   169 	pCtx->StringToLocalUTF8(params[3], params[4], ret, NULL);
   170 
   171 	return 1;
   172 }
   173 
   174 void RegexHandler::OnHandleDestroy(HandleType_t type, void *object)
   175 {
   176 	RegEx *x = (RegEx *)object;
   177 
   178 	x->Clear();
   179 	delete x;
   180 }
   181 
   182 const sp_nativeinfo_t regex_natives[] = 
   183 {
   184 	{"GetRegexSubString",			GetRegexSubString},
   185 	{"MatchRegex",					MatchRegex},
   186 	{"CompileRegex",				CompileRegex},
   187 	{NULL,							NULL},
   188 };