1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/extensions/regex/extension.cpp Wed Mar 26 03:52:37 2008 +0000
1.3 @@ -0,0 +1,188 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod Sample Extension
1.8 + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include "extension.h"
1.36 +
1.37 +#include <sh_string.h>
1.38 +#include "pcre.h"
1.39 +#include "CRegEx.h"
1.40 +using namespace SourceHook;
1.41 +
1.42 +/**
1.43 + * @file extension.cpp
1.44 + * @brief Implement extension code here.
1.45 + */
1.46 +
1.47 +RegexExtension g_RegexExtension; /**< Global singleton for extension's main interface */
1.48 +
1.49 +SMEXT_LINK(&g_RegexExtension);
1.50 +
1.51 +RegexHandler g_RegexHandler;
1.52 +HandleType_t g_RegexHandle=0;
1.53 +
1.54 +
1.55 +
1.56 +bool RegexExtension::SDK_OnLoad(char *error, size_t err_max, bool late)
1.57 +{
1.58 + g_pShareSys->AddNatives(myself,regex_natives);
1.59 + g_RegexHandle = g_pHandleSys->CreateType("Regex", &g_RegexHandler, 0, NULL, NULL, myself->GetIdentity(), NULL);
1.60 + return true;
1.61 +}
1.62 +
1.63 +void RegexExtension::SDK_OnUnload()
1.64 +{
1.65 + g_pHandleSys->RemoveType(g_RegexHandle, myself->GetIdentity());
1.66 +
1.67 +}
1.68 +
1.69 +static cell_t CompileRegex(IPluginContext *pCtx, const cell_t *params)
1.70 +{
1.71 + char *regex;
1.72 + pCtx->LocalToString(params[1], ®ex);
1.73 +
1.74 + RegEx *x = new RegEx();
1.75 +
1.76 + if (x->Compile(regex, params[2]) == 0)
1.77 + {
1.78 + cell_t *eOff;
1.79 + pCtx->LocalToPhysAddr(params[5], &eOff);
1.80 + const char *err = x->mError;
1.81 + *eOff = x->mErrorOffset;
1.82 + pCtx->StringToLocal(params[3], params[4], err ? err:"unknown");
1.83 + return 0;
1.84 + }
1.85 +
1.86 + return g_pHandleSys->CreateHandle(g_RegexHandle, (void*)x, pCtx->GetIdentity(), myself->GetIdentity(), NULL);
1.87 +}
1.88 +
1.89 +
1.90 +static cell_t MatchRegex(IPluginContext *pCtx, const cell_t *params)
1.91 +{
1.92 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.93 + HandleError err;
1.94 + HandleSecurity sec;
1.95 + sec.pOwner = NULL;
1.96 + sec.pIdentity = myself->GetIdentity();
1.97 +
1.98 + RegEx *x;
1.99 +
1.100 + if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
1.101 + {
1.102 + return pCtx->ThrowNativeError("Invalid file handle %x (error %d)", hndl, err);
1.103 + }
1.104 +
1.105 + if (!x)
1.106 + {
1.107 + pCtx->ThrowNativeError("Regex data not found\n");
1.108 +
1.109 + return 0;
1.110 + }
1.111 +
1.112 + char *str;
1.113 + pCtx->LocalToString(params[2], &str);
1.114 +
1.115 + int e = x->Match(str);
1.116 +
1.117 + if (e == -1)
1.118 + {
1.119 + /* there was a match error. move on. */
1.120 + cell_t *res;
1.121 + pCtx->LocalToPhysAddr(params[3], &res);
1.122 + *res = x->mErrorOffset;
1.123 + /* only clear the match results, since the regex object
1.124 + may still be referenced later */
1.125 + x->ClearMatch();
1.126 +
1.127 + return -1;
1.128 + }
1.129 + else if (e == 0)
1.130 + {
1.131 + /* only clear the match results, since the regex object
1.132 + may still be referenced later */
1.133 + x->ClearMatch();
1.134 +
1.135 + return 0;
1.136 + }
1.137 + else
1.138 + {
1.139 + return x->mSubStrings;
1.140 + }
1.141 +}
1.142 +
1.143 +static cell_t GetRegexSubString(IPluginContext *pCtx, const cell_t *params)
1.144 +{
1.145 + Handle_t hndl=static_cast<Handle_t>(params[1]);
1.146 + HandleError err;
1.147 + HandleSecurity sec;
1.148 + sec.pOwner=NULL;
1.149 + sec.pIdentity=myself->GetIdentity();
1.150 +
1.151 + RegEx *x;
1.152 +
1.153 + if ((err=g_pHandleSys->ReadHandle(hndl, g_RegexHandle, &sec, (void **)&x)) != HandleError_None)
1.154 + {
1.155 + return pCtx->ThrowNativeError("Invalid file handle %x (error %d)", hndl, err);
1.156 + }
1.157 +
1.158 + if (!x)
1.159 + {
1.160 + pCtx->ThrowNativeError("Regex data not found\n");
1.161 + return 0;
1.162 + }
1.163 +
1.164 + static char buffer[4096];
1.165 + const char *ret=x->GetSubstring(params[2], buffer, sizeof(buffer));
1.166 +
1.167 + if(!ret)
1.168 + {
1.169 + return 0;
1.170 + }
1.171 +
1.172 + pCtx->StringToLocalUTF8(params[3], params[4], ret, NULL);
1.173 +
1.174 + return 1;
1.175 +}
1.176 +
1.177 +void RegexHandler::OnHandleDestroy(HandleType_t type, void *object)
1.178 +{
1.179 + RegEx *x = (RegEx *)object;
1.180 +
1.181 + x->Clear();
1.182 + delete x;
1.183 +}
1.184 +
1.185 +const sp_nativeinfo_t regex_natives[] =
1.186 +{
1.187 + {"GetRegexSubString", GetRegexSubString},
1.188 + {"MatchRegex", MatchRegex},
1.189 + {"CompileRegex", CompileRegex},
1.190 + {NULL, NULL},
1.191 +};