Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #if !defined DB_MULTIGET_MAX_ENTRIES
- #define DB_MULTIGET_MAX_ENTRIES (16)
- #endif
- #if !defined DB_MULTISET_MAX_ENTRIES
- #define DB_MULTISET_MAX_ENTRIES (16)
- #endif
- #if !defined DB_MULTISET_MAX_STRING_SIZE
- #define DB_MULTISET_MAX_STRING_SIZE (DB::MAX_ENTRY_STRING)
- #endif
- #if !defined DB_CHECK_STRING_LENGTH
- #define DB_CHECK_STRING_LENGTH (false)
- #endif
- dbglobal bool:DB::MultiSet(table, key, const szTypeDefinitions[], { _, Float }:...) {
- new
- iEntries = numargs() - 3
- ;
- if (iEntries & 0b1) {
- DB::Error("A parameter is missing in DB::MultiSet; expecting a variable/value in the end.", numargs() - 3);
- return false;
- }
- iEntries /= 2;
- if (iEntries > DB::MULTISET_MAX_ENTRIES) {
- DB::Error("Too many entires passed to DB::MultiSet; entires: %d, limit: %d.", iEntries, DB::MULTISET_MAX_ENTRIES);
- return false;
- }
- new
- iNumTypeDefinitions = strlen(szTypeDefinitions)
- ;
- if (iEntries != iNumTypeDefinitions) {
- DB::Error("The number of type definitions doesn't match the number of entries passed to DB::MultiSet; typedefs: %d, entries: %d.", iNumTypeDefinitions, iEntries);
- return false;
- }
- for (new i = 0; i < iNumTypeDefinitions; i++) {
- switch (szTypeDefinitions[i]) {
- case 'i', 'd', 'f', 's': { }
- default: {
- DB::Error("Unknown type definition passed to DB::MultiSet; expected: i/s/f, given: %c.", szTypeDefinitions[i]);
- return false;
- }
- }
- }
- if (! DB::Get())
- {
- return false;
- }
- new
- szColumn[DB::MAX_COLUMN_NAME],
- iColumnArg,
- szValue[DB::MULTISET_MAX_STRING_SIZE * 2]
- ;
- format(g_Query, sizeof(g_Query), "UPDATE `%s` SET ", g_TableData[table][DB::TABLE_NAME]);
- for (new iEntry = 0; iEntry < iEntries; iEntry++) {
- iColumnArg = 3 + iEntry * 2;
- __getstringarg(szColumn, iColumnArg);
- ++iColumnArg;
- #if (DB::CHECK_STRING_LENGTH)
- if (strlen(szColumn) >= DB::MAX_COLUMN_NAME)
- return false;
- #endif
- strcat(g_Query, "`");
- strcat(g_Query, szColumn);
- strcat(g_Query, "`=");
- switch (szTypeDefinitions[iEntry]) {
- case 'i', 'd': {
- valstr(szValue, getarg(iColumnArg));
- }
- case 'f': {
- format(szValue, sizeof(szValue), "%f", Float:getarg(iColumnArg));
- }
- case 's': {
- __getstringarg(szValue, iColumnArg, DB::MULTISET_MAX_STRING_SIZE);
- szValue[DB::MULTISET_MAX_STRING_SIZE - 1] = EOS;
- DB::Escape(szValue);
- strcat(g_Query, "'");
- }
- }
- strcat(g_Query, szValue);
- if (szTypeDefinitions[iEntry] == 's')
- strcat(g_Query, "'");
- if (iEntry < iEntries - 1)
- strcat(g_Query, ", ");
- }
- new endstr[128];
- format(endstr, sizeof(endstr), " WHERE `%s`='%d'", g_TableData[table][DB::TABLE_KEY], key);
- strcat(g_Query, endstr);
- new
- DBResult:i_DBResult = db_query(g_Database, g_Query)
- ;
- if (i_DBResult)
- {
- db_free_result(i_DBResult);
- return true;
- }
- else
- {
- return false;
- }
- }
- dbglobal bool:DB::MultiGet(table, key, const szTypeDefinitions[], { _, Float }:...) {
- new
- iEntries = numargs() - 3
- ;
- if (iEntries & 0b1) {
- DB::Error("A parameter is missing in DB::MultiGet; expecting a variable %d in the end.", numargs() - 3);
- return false;
- }
- iEntries /= 2;
- if (iEntries > DB::MULTIGET_MAX_ENTRIES) {
- DB::Error("Too many entires passed to DB::MultiGet; entires: %d, limit: %d.", iEntries, DB::MULTIGET_MAX_ENTRIES);
- return false;
- }
- new
- iNumTypeDefinitions,
- iTypeDefinitions[DB::MULTIGET_MAX_ENTRIES char],
- iTypeLengths[DB::MULTIGET_MAX_ENTRIES]
- ;
- for (new i = 0, l = strlen(szTypeDefinitions); i < l; i++) {
- switch (szTypeDefinitions[i]) {
- case 'i', 'd', 'f': {
- iTypeDefinitions{ iNumTypeDefinitions++ } = szTypeDefinitions[i];
- }
- case 's': {
- if (szTypeDefinitions[i + 1] == '[' && szTypeDefinitions[i + 2]) {
- ++i;
- new
- szLength[11],
- iEndingBracket = strfind(szTypeDefinitions, "]", .pos = i + 2)
- ;
- if (iEndingBracket != -1) {
- strmid(szLength, szTypeDefinitions, i + 1, iEndingBracket);
- iTypeLengths[iNumTypeDefinitions] = strval(szLength);
- if (iTypeLengths[iNumTypeDefinitions] <= 0) {
- DB::Error("Invalid string length given in the type definitions for DB::MultiGet: %d.", iTypeLengths[iNumTypeDefinitions]);
- return false;
- }
- iTypeDefinitions{ iNumTypeDefinitions++ } = 's';
- i = iEndingBracket;
- continue;
- }
- }
- DB::Error("String size has to be passed in the type definitions for DB::MultiGet; example: \"iffs[32]ii\".", iNumTypeDefinitions, iEntries);
- return false;
- }
- default: {
- DB::Error("Unknown type definition passed to DB::MultiGet; expected: i/s/f, given: %c.", szTypeDefinitions[i]);
- return false;
- }
- }
- }
- if (iEntries != iNumTypeDefinitions) {
- DB::Error("The number of type definitions doesn't match the number of entries passed to DB::MultiGet; typedefs: %d, entries: %d.", iNumTypeDefinitions, iEntries);
- return false;
- }
- if (!DB::Get())
- return false;
- new
- szColumn[DB::MAX_COLUMN_NAME],
- iColumnArg,
- g_szzBiffer[DB::BUFFER_SIZE],
- tempquer[128]
- ;
- g_szzBiffer = "SELECT `";
- for (new iEntry = 0; iEntry < iEntries; iEntry++) {
- iColumnArg = 3 + iEntry * 2;
- __getstringarg(szColumn, iColumnArg);
- #if (DB::CHECK_STRING_LENGTH)
- if (strlen(szColumn) >= DB::MAX_COLUMN_NAME)
- return false;
- #endif
- strcat(g_szzBiffer, szColumn);
- if (iEntry < iEntries - 1)
- strcat(g_szzBiffer, "`,`");
- }
- format(tempquer, sizeof(tempquer), "` FROM `%s` WHERE `%s`='%d'", g_TableData[table][DB::TABLE_NAME], g_TableData[table][DB::TABLE_KEY], key);
- strcat(g_szzBiffer, tempquer);
- new
- DBResult:dbrResult
- ;
- dbrResult = db_query(g_Database, g_szzBiffer);
- if (dbrResult) {
- new
- iRows = db_num_rows(dbrResult)
- ;
- if (iRows == 1) {
- new
- iFields = db_num_fields(dbrResult)
- ;
- if (iEntries != iFields)
- DB::Warning("The number of entries requested doesn't match the given number; requested: %d, given: %d", iEntries, iFields);
- for (new iField = 0; iField < iFields; iField++) {
- if (iTypeDefinitions{ iField } == 's')
- db_get_field(dbrResult, iField, g_szzBiffer, iTypeLengths[iField] - 1);
- else
- db_get_field(dbrResult, iField, g_szzBiffer, sizeof(g_szzBiffer) - 1);
- switch (iTypeDefinitions{ iField }) {
- case 'i', 'd': {
- setarg(3 + iField * 2 + 1, .value = strval(g_szzBiffer));
- }
- case 'f': {
- setarg(3 + iField * 2 + 1, .value = _:floatstr(g_szzBiffer));
- }
- case 's': {
- __setstringarg(3 + iField * 2 + 1, g_szzBiffer);
- }
- }
- }
- } else if (iRows > 1) {
- DB::Error("Multiple rows fetched from one Key; Key: %d, rows: %d", key, iRows);
- db_free_result(dbrResult);
- return false;
- }
- db_free_result(dbrResult);
- return true;
- }
- return false;
- }
- dbstatic __getstringarg(dest[], arg, len = sizeof (dest))
- {
- // Get the address of the previous function's stack. First get the index of
- // the argument required.
- #emit LOAD.S.pri arg
- // Then convert that number to bytes from cells.
- #emit SMUL.C 4
- // Get the previous function's frame. Stored in variable 0 (in the current
- // frame). Parameters are FRM+n+12, locals are FRM-n, previous frame is
- // FRM+0, return address is FRM+4, parameter count is FRM+8. We could add
- // checks that "arg * 4 < *(*(FRM + 0) + 8)", for the previous frame parameter
- // count (in C pointer speak).
- #emit LOAD.S.alt 0
- // Add the frame pointer to the argument offset in bytes.
- #emit ADD
- // Add 12 to skip over the function header.
- #emit ADD.C 12
- // Load the address stored in the specified address.
- #emit LOAD.I
- // Push the length for "strcat".
- #emit PUSH.S len
- // Push the address we just determined was the source.
- #emit PUSH.pri
- // Load the address of the destination.
- #emit LOAD.S.alt dest
- // Blank the first cell so "strcat" behaves like "strcpy".
- #emit CONST.pri 0
- // Store the loaded number 0 to the loaded address.
- #emit STOR.I
- // Push the loaded address.
- #emit PUSH.alt
- // Push the number of parameters passed (in bytes) to the function.
- #emit PUSH.C 12
- // Call the function.
- #emit SYSREQ.C strcat
- // Restore the stack to its level before we called this native.
- #emit STACK 16
- }
- stock __setstringarg(iArg, const szValue[], iLength = sizeof(szValue)) {
- new
- iAddress
- ;
- // Get the address of the previous function's stack. First get the index of
- // the argument required.
- #emit LOAD.S.pri iArg
- // Then convert that number to bytes from cells.
- #emit SMUL.C 4
- // Get the previous function's frame.
- #emit LOAD.S.alt 0
- // Add the frame pointer to the argument offset in bytes.
- #emit ADD
- // Add 12 to skip over the function header.
- #emit ADD.C 12
- // Load the address stored in the specified address.
- #emit LOAD.I
- #emit STOR.S.PRI iAddress
- // Push the length (last argument first)
- #emit PUSH.S iLength
- // Push the new value (source) szValue
- #emit PUSH.S szValue
- // Blank out the first cell of the argument
- #emit CONST.pri 0
- #emit SREF.S.pri iAddress
- // Push the destination
- #emit PUSH.S iAddress
- // Push the number of parameters passed (in bytes) to the function.
- #emit PUSH.C 12
- // Call the function.
- #emit SYSREQ.C strcat
- // Restore the stack to its level before we called this native.
- #emit STACK 16
- }
Advertisement
Add Comment
Please, Sign In to add comment