Skip to content

Commit

Permalink
[#6]: pawn Json::FindFirst implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
rejchev committed Sep 1, 2023
1 parent f3014dc commit 5fe6eb9
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 10 deletions.
15 changes: 15 additions & 0 deletions pawn/scripting/include/jansson.inc
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ enum JsonObjectUpdateType
UpdRecursive
};

// Simple validator
//
// @param obj Json obj [must not be freed]
//
// @return true on valid/false
typedef JsonValidator = function bool(const Json obj);

// Generic type for encoding JSON.
methodmap Json < Handle
{
Expand Down Expand Up @@ -92,6 +99,14 @@ methodmap Json < Handle
// @return size
public static native int SizeOf(const Json json, int flags = 0);

// Find first occurrence of interesting json (with type filter) [it must by jtObject or jtArray]
//
// @param condition Condition (see JsonValidator)
// @param type Interesting json items type to find in (jtInvalid to find in all)
//
// @return Json or null
public native Json FindFirst(JsonValidator condition, JsonType type = jtInvalid);

// Writes the JSON string representation to a file.
//
// @param file File to write to.
Expand Down
3 changes: 2 additions & 1 deletion public/IJansson.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <ISourceMod.h>
#include <vector>
#include <cstring>
#include <functional>

#define SMINTERFACE_JANSSON_NAME "IJansson"

Expand Down Expand Up @@ -234,7 +235,7 @@ namespace nJansson

public:
virtual bool equal(const IJson* json) const =0;
virtual IJson* find(const JsonType& type, bool (*)(const IJson*)) const =0;
virtual IJson* find(const JsonType& type, const std::function<bool(const IJson*)>& condition) const =0;

public:
virtual bool get(long long *value) =0;
Expand Down
4 changes: 3 additions & 1 deletion src/jansson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ Jansson::~Jansson() {
}

void Jansson::close(IJson *json) {
delete (Json*) json;

if(json != nullptr)
delete (Json*) json;
}

JsonError_t Jansson::ToKnownError(const json_error_t *error) {
Expand Down
12 changes: 5 additions & 7 deletions src/json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,17 +345,15 @@ const char *Json::dump(const size_t &flags) const
return isOK() ? json_dumps(json(), flags) : nullptr;
}

IJson *Json::find(const JsonType &type, bool (*cond)(const IJson *)) const
IJson *Json::find(const JsonType &type, const std::function<bool(const IJson*)>& condition) const
{
const JsonType& selfType = this->type();

if(selfType != jtObject && selfType != jtArray)
return nullptr;

auto isObjectValid =[](
const JsonType& ctype,
bool (*cond)(const IJson*),
json_t* ptr) -> bool
auto simpleValidator = [] (
const JsonType& ctype, const std::function<bool(const IJson*)>& cond, json_t* ptr) -> bool
{
if(!ptr || (ctype != jtInvalid && innerTypeConversion(ptr->type) != ctype))
return false;
Expand All @@ -378,7 +376,7 @@ IJson *Json::find(const JsonType &type, bool (*cond)(const IJson *)) const
if(!(pBuffer = json_object_get(m_pJson, key)))
continue;

if(!isObjectValid(type, cond, pBuffer))
if(!simpleValidator(type, condition, pBuffer))
{
json_decref(pBuffer);
pBuffer = nullptr;
Expand All @@ -392,7 +390,7 @@ IJson *Json::find(const JsonType &type, bool (*cond)(const IJson *)) const
if(!(pBuffer = json_array_get(m_pJson, i)))
continue;

if(!isObjectValid(type, cond, pBuffer))
if(!simpleValidator(type, condition, pBuffer))
{
json_decref(pBuffer);
pBuffer = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion src/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace nJansson

public:
bool equal(const IJson* json) const override;
IJson* find(const JsonType& type, bool (*cond)(const IJson*)) const override;
IJson* find(const JsonType& type, const std::function<bool(const IJson*)>& condition) const override;

public:
bool get(long long *value) override;
Expand Down
49 changes: 49 additions & 0 deletions src/natives/json_natives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,54 @@ cell_t JsonSizeOf(IPluginContext *pContext, const cell_t *params) {
return size;
}

cell_t JsonFindFirst(IPluginContext *pContext, const cell_t *params) {
const nJansson::IHandleType* pType;
if((pType = nJansson::GetHandleType(pJansson, "Json")) == nullptr)
return 0;

HandleSecurity sec {pContext->GetIdentity(), myself->GetIdentity()};

nJansson::IJson* json;
if((json = nJansson::ReadJsonHandle(params[1], pType, &sec)) == nullptr)
return 0;

if(json->type() != nJansson::jtObject && json->type() != nJansson::jtArray)
return 0;

IPluginFunction* pFunc;
if(!(pFunc = pContext->GetFunctionById((funcid_t)params[2])))
return 0;

const auto& interestingType = (nJansson::JsonType&)params[3];

using JsonValidator = std::function<bool(const nJansson::IJson*)>;

JsonValidator funcCondition = {[&](const nJansson::IJson* ptr) -> bool
{
Handle_t handle;

if((handle = nJansson::CreateHandle((void*)ptr, pType, &sec)) == BAD_HANDLE)
return false;

bool result {};

pFunc->PushCell(interestingType);
pFunc->PushCell((cell_t)handle);
pFunc->Execute((cell_t*)&(result));

// Json object (ptr) is not allocated
nJansson::FreeHandle(handle, nullptr, pType, &sec);

return result;
}};

nJansson::IJson* pRes;
if((pRes = json->find(interestingType, funcCondition)) == nullptr)
return 0;

return (cell_t) nJansson::CreateHandle((void*)pRes, pType, &sec);
}

const sp_nativeinfo_t JSON_NATIVES[] =
{
{"Json.Json", JsonCreate},
Expand All @@ -391,6 +439,7 @@ const sp_nativeinfo_t JSON_NATIVES[] =
{"Json.Dump", JsonDump},
{"Json.ToFile", JsonDumpToFile},
{"Json.Equal", JsonEqual},
{"Json.FindFirst", JsonFindFirst},

{"Json.AsInt", JsonGetInt},
{"Json.TryAsInt", JsonGetIntEx},
Expand Down
1 change: 1 addition & 0 deletions src/natives/json_natives.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ extern cell_t JsonGetInt64(SourcePawn::IPluginContext *pContext, const cell_t *p
extern cell_t JsonClear(SourcePawn::IPluginContext *pContext, const cell_t *params);
extern cell_t JsonSize(SourcePawn::IPluginContext *pContext, const cell_t *params);
extern cell_t JsonSizeOf(SourcePawn::IPluginContext *pContext, const cell_t *params);
extern cell_t JsonFindFirst(SourcePawn::IPluginContext *pContext, const cell_t *params);


extern const sp_nativeinfo_t JSON_NATIVES[];
Expand Down

0 comments on commit 5fe6eb9

Please sign in to comment.