Rewritten SVQC stringbuffer saving routines (which is part of yet unfinished databuff...
authorvortex <vortex@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 28 Mar 2013 20:24:13 +0000 (20:24 +0000)
committervortex <vortex@d7cf8633-e32d-0410-b094-e92efae38249>
Thu, 28 Mar 2013 20:24:13 +0000 (20:24 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11930 d7cf8633-e32d-0410-b094-e92efae38249

host_cmd.c
progsvm.h
prvm_cmds.c
zone.c
zone.h

index 6a56f78..6a0b991 100644 (file)
@@ -551,7 +551,7 @@ LOAD / SAVE GAME
 void Host_Savegame_to(prvm_prog_t *prog, const char *name)
 {
        qfile_t *f;
-       int             i, k, l, lightstyles = 64;
+       int             i, k, l, numbuffers, lightstyles = 64;
        char    comment[SAVEGAME_COMMENT_LENGTH+1];
        char    line[MAX_INPUTLINE];
        qboolean isserver;
@@ -641,11 +641,13 @@ void Host_Savegame_to(prvm_prog_t *prog, const char *name)
                        FS_Printf(f,"sv.sound_precache %i %s\n", i, sv.sound_precache[i]);
 
        // darkplaces extension - save buffers
-       for (i = 0; i < (int)Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray); i++)
+       numbuffers = Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray);
+       for (i = 0; i < numbuffers; i++)
        {
                prvm_stringbuffer_t *stringbuffer = (prvm_stringbuffer_t*) Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i);
                if(stringbuffer && (stringbuffer->flags & STRINGBUFFER_SAVED))
                {
+                       FS_Printf(f,"sv.buffer %i %i \"string\"\n", i, stringbuffer->flags & STRINGBUFFER_QCFLAGS);
                        for(k = 0; k < stringbuffer->num_strings; k++)
                        {
                                if (!stringbuffer->strings[k])
@@ -753,6 +755,11 @@ Host_Loadgame_f
 ===============
 */
 
+prvm_stringbuffer_t *BufStr_FindCreateReplace (prvm_prog_t *prog, int bufindex, int flags, char *format);
+void BufStr_Set(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer, int strindex, const char *str);
+void BufStr_Del(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer);
+void BufStr_Flush(prvm_prog_t *prog);
+
 static void Host_Loadgame_f (void)
 {
        prvm_prog_t *prog = SVVM_prog;
@@ -764,12 +771,11 @@ static void Host_Loadgame_f (void)
        const char *t;
        char *text;
        prvm_edict_t *ent;
-       int i, k;
+       int i, k, numbuffers;
        int entnum;
        int version;
        float spawn_parms[NUM_SPAWN_PARMS];
        prvm_stringbuffer_t *stringbuffer;
-       size_t alloclen;
 
        if (Cmd_Argc() != 2)
        {
@@ -988,6 +994,8 @@ static void Host_Loadgame_f (void)
                        memset(sv.lightstyles[0], 0, sizeof(sv.lightstyles));
                        memset(sv.model_precache[0], 0, sizeof(sv.model_precache));
                        memset(sv.sound_precache[0], 0, sizeof(sv.sound_precache));
+                       BufStr_Flush(prog);
+
                        while (COM_ParseToken_Simple(&t, false, false, true))
                        {
                                if (!strcmp(com_token, "sv.lightstyles"))
@@ -1023,44 +1031,48 @@ static void Host_Loadgame_f (void)
                                        else
                                                Con_Printf("unsupported sound %i \"%s\"\n", i, com_token);
                                }
+                               else if (!strcmp(com_token, "sv.buffer"))
+                               {
+                                       if (COM_ParseToken_Simple(&t, false, false, true))
+                                       {
+                                               i = atoi(com_token);
+                                               if (i >= 0)
+                                               {
+                                                       k = STRINGBUFFER_SAVED;
+                                                       if (COM_ParseToken_Simple(&t, false, false, true))
+                                                               k |= atoi(com_token);
+                                                       if (!BufStr_FindCreateReplace(prog, i, k, "string"))
+                                                               Con_Printf("failed to create stringbuffer %i\n", i);
+                                               }
+                                               else
+                                                       Con_Printf("unsupported stringbuffer index %i \"%s\"\n", i, com_token);
+                                       }
+                                       else
+                                               Con_Printf("unexpected end of line when parsing sv.buffer (expected buffer index)\n");
+                               }
                                else if (!strcmp(com_token, "sv.bufstr"))
                                {
-                                       COM_ParseToken_Simple(&t, false, false, true);
-                                       i = atoi(com_token);
-                                       COM_ParseToken_Simple(&t, false, false, true);
-                                       k = atoi(com_token);
-                                       COM_ParseToken_Simple(&t, false, false, true);
-                                       stringbuffer = (prvm_stringbuffer_t*) Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i);
-                                       // VorteX: nasty code, cleanup required
-                                       // create buffer at this index
-                                       if(!stringbuffer) 
-                                               stringbuffer = (prvm_stringbuffer_t *) Mem_ExpandableArray_AllocRecordAtIndex(&prog->stringbuffersarray, i);
-                                       if (!stringbuffer)
-                                               Con_Printf("cant write string %i into buffer %i\n", k, i);
+                                       if (!COM_ParseToken_Simple(&t, false, false, true))
+                                               Con_Printf("unexpected end of line when parsing sv.bufstr\n");
                                        else
                                        {
-                                               // code copied from VM_bufstr_set
-                                               // expand buffer
-                                               if (stringbuffer->max_strings <= i)
+                                               i = atoi(com_token);
+                                               stringbuffer = BufStr_FindCreateReplace(prog, i, STRINGBUFFER_SAVED, "string");
+                                               if (stringbuffer)
                                                {
-                                                       char **oldstrings = stringbuffer->strings;
-                                                       stringbuffer->max_strings = max(stringbuffer->max_strings * 2, 128);
-                                                       while (stringbuffer->max_strings <= i)
-                                                               stringbuffer->max_strings *= 2;
-                                                       stringbuffer->strings = (char **) Mem_Alloc(prog->progs_mempool, stringbuffer->max_strings * sizeof(stringbuffer->strings[0]));
-                                                       if (stringbuffer->num_strings > 0)
-                                                               memcpy(stringbuffer->strings, oldstrings, stringbuffer->num_strings * sizeof(stringbuffer->strings[0]));
-                                                       if (oldstrings)
-                                                               Mem_Free(oldstrings);
+                                                       if (COM_ParseToken_Simple(&t, false, false, true))
+                                                       {
+                                                               k = atoi(com_token);
+                                                               if (COM_ParseToken_Simple(&t, false, false, true))
+                                                                       BufStr_Set(prog, stringbuffer, k, com_token);
+                                                               else
+                                                                       Con_Printf("unexpected end of line when parsing sv.bufstr (expected string)\n");
+                                                       }
+                                                       else
+                                                               Con_Printf("unexpected end of line when parsing sv.bufstr (expected strindex)\n");
                                                }
-                                               // allocate string
-                                               stringbuffer->num_strings = max(stringbuffer->num_strings, k + 1);
-                                               if(stringbuffer->strings[k])
-                                                       Mem_Free(stringbuffer->strings[k]);
-                                               stringbuffer->strings[k] = NULL;
-                                               alloclen = strlen(com_token) + 1;
-                                               stringbuffer->strings[k] = (char *)Mem_Alloc(prog->progs_mempool, alloclen);
-                                               memcpy(stringbuffer->strings[k], com_token, alloclen);
+                                               else
+                                                       Con_Printf("failed to create stringbuffer %i \"%s\"\n", i, com_token);
                                        }
                                }       
                                // skip any trailing text or unrecognized commands
@@ -1071,6 +1083,15 @@ static void Host_Loadgame_f (void)
        }
        Mem_Free(text);
 
+       // remove all temporary flagged string buffers (ones created with BufStr_FindCreateReplace)
+       numbuffers = Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray);
+       for (i = 0; i < numbuffers; i++)
+       {
+               if ( (stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i)) )
+                       if (stringbuffer->flags & STRINGBUFFER_TEMP)
+                               BufStr_Del(prog, stringbuffer);
+       }
+
        if(developer_entityparsing.integer)
                Con_Printf("Host_Loadgame_f: finished\n");
 
index c4e0f3d..406a9eb 100644 (file)
--- a/progsvm.h
+++ b/progsvm.h
@@ -513,7 +513,9 @@ typedef struct prvm_prog_funcoffsets_s
 prvm_prog_funcoffsets_t;
 
 // stringbuffer flags
-#define STRINGBUFFER_SAVED     1 // saved in savegames
+#define STRINGBUFFER_SAVED     1   // saved in savegames
+#define STRINGBUFFER_QCFLAGS   1   // allowed to be set by QC
+#define STRINGBUFFER_TEMP      128 // internal use ONLY 
 typedef struct prvm_stringbuffer_s
 {
        int max_strings;
index ce69930..c9f5527 100644 (file)
@@ -4629,6 +4629,94 @@ static int BufStr_SortStringsDOWN (const void *in1, const void *in2)
        return strncmp(b, a, stringbuffers_sortlength);
 }
 
+prvm_stringbuffer_t *BufStr_FindCreateReplace (prvm_prog_t *prog, int bufindex, int flags, char *format)
+{
+       prvm_stringbuffer_t *stringbuffer;
+       int i;
+
+       if (bufindex < 0)
+               return NULL;
+
+       // find buffer with wanted index
+       if (bufindex < (int)Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray))
+       {
+               if ( (stringbuffer = (prvm_stringbuffer_t*) Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, bufindex)) )
+               {
+                       if (stringbuffer->flags & STRINGBUFFER_TEMP)
+                               stringbuffer->flags = flags; // created but has not been used yet
+                       return stringbuffer;
+               }
+               return NULL;
+       }
+
+       // allocate new buffer with wanted index
+       while(1)
+       {
+               stringbuffer = (prvm_stringbuffer_t *) Mem_ExpandableArray_AllocRecord(&prog->stringbuffersarray);
+               stringbuffer->flags = STRINGBUFFER_TEMP;
+               for (i = 0;stringbuffer != Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i);i++);
+               if (i == bufindex)
+               {
+                       stringbuffer->flags = flags; // mark as used
+                       break;
+               }
+       }
+       return stringbuffer;
+}
+
+void BufStr_Set(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer, int strindex, const char *str)
+{
+       size_t  alloclen;
+
+       if (!stringbuffer || strindex < 0)
+               return;
+
+       BufStr_Expand(prog, stringbuffer, strindex);
+       stringbuffer->num_strings = max(stringbuffer->num_strings, strindex + 1);
+       if (stringbuffer->strings[strindex])
+               Mem_Free(stringbuffer->strings[strindex]);
+       stringbuffer->strings[strindex] = NULL;
+
+       if (str)
+       {
+               // not the NULL string!
+               alloclen = strlen(str) + 1;
+               stringbuffer->strings[strindex] = (char *)Mem_Alloc(prog->progs_mempool, alloclen);
+               memcpy(stringbuffer->strings[strindex], str, alloclen);
+       }
+
+       BufStr_Shrink(prog, stringbuffer);
+}
+
+void BufStr_Del(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer)
+{
+       int i;
+       
+       if (!stringbuffer)
+               return;
+
+       for (i = 0;i < stringbuffer->num_strings;i++)
+               if (stringbuffer->strings[i])
+                       Mem_Free(stringbuffer->strings[i]);
+       if (stringbuffer->strings)
+               Mem_Free(stringbuffer->strings);
+       if(stringbuffer->origin)
+               PRVM_Free((char *)stringbuffer->origin);
+       Mem_ExpandableArray_FreeRecord(&prog->stringbuffersarray, stringbuffer);
+}
+
+void BufStr_Flush(prvm_prog_t *prog)
+{
+       prvm_stringbuffer_t *stringbuffer;
+       int i, numbuffers;
+
+       numbuffers = Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray);
+       for (i = 0; i < numbuffers; i++)
+               if ( (stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i)) )
+                       BufStr_Del(prog, stringbuffer);
+       Mem_ExpandableArray_NewArray(&prog->stringbuffersarray, prog->progs_mempool, sizeof(prvm_stringbuffer_t), 64);
+}
+
 /*
 ========================
 VM_buf_create
@@ -4656,7 +4744,7 @@ void VM_buf_create (prvm_prog_t *prog)
        stringbuffer->origin = PRVM_AllocationOrigin(prog);
        // optional flags parm
        if (prog->argc >= 2)
-               stringbuffer->flags = (int)PRVM_G_FLOAT(OFS_PARM1) & 0xFF;
+               stringbuffer->flags = (int)PRVM_G_FLOAT(OFS_PARM1) & STRINGBUFFER_QCFLAGS;
        PRVM_G_FLOAT(OFS_RETURN) = i;
 }
 
@@ -4675,17 +4763,7 @@ void VM_buf_del (prvm_prog_t *prog)
        VM_SAFEPARMCOUNT(1, VM_buf_del);
        stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, (int)PRVM_G_FLOAT(OFS_PARM0));
        if (stringbuffer)
-       {
-               int i;
-               for (i = 0;i < stringbuffer->num_strings;i++)
-                       if (stringbuffer->strings[i])
-                               Mem_Free(stringbuffer->strings[i]);
-               if (stringbuffer->strings)
-                       Mem_Free(stringbuffer->strings);
-               if(stringbuffer->origin)
-                       PRVM_Free((char *)stringbuffer->origin);
-               Mem_ExpandableArray_FreeRecord(&prog->stringbuffersarray, stringbuffer);
-       }
+               BufStr_Del(prog, stringbuffer);
        else
        {
                VM_Warning(prog, "VM_buf_del: invalid buffer %i used in %s\n", (int)PRVM_G_FLOAT(OFS_PARM0), prog->name);
@@ -4885,7 +4963,6 @@ void bufstr_set(float bufhandle, float string_index, string str) = #466;
 */
 void VM_bufstr_set (prvm_prog_t *prog)
 {
-       size_t alloclen;
        int                             strindex;
        prvm_stringbuffer_t *stringbuffer;
        const char              *news;
@@ -4905,23 +4982,8 @@ void VM_bufstr_set (prvm_prog_t *prog)
                return;
        }
 
-       BufStr_Expand(prog, stringbuffer, strindex);
-       stringbuffer->num_strings = max(stringbuffer->num_strings, strindex + 1);
-
-       if(stringbuffer->strings[strindex])
-               Mem_Free(stringbuffer->strings[strindex]);
-       stringbuffer->strings[strindex] = NULL;
-
-       if(PRVM_G_INT(OFS_PARM2))
-       {
-               // not the NULL string!
-               news = PRVM_G_STRING(OFS_PARM2);
-               alloclen = strlen(news) + 1;
-               stringbuffer->strings[strindex] = (char *)Mem_Alloc(prog->progs_mempool, alloclen);
-               memcpy(stringbuffer->strings[strindex], news, alloclen);
-       }
-
-       BufStr_Shrink(prog, stringbuffer);
+       news = PRVM_G_STRING(OFS_PARM2);
+       BufStr_Set(prog, stringbuffer, strindex, news);
 }
 
 /*
diff --git a/zone.c b/zone.c
index 1638636..2c72c11 100644 (file)
--- a/zone.c
+++ b/zone.c
@@ -697,44 +697,6 @@ void Mem_ExpandableArray_FreeArray(memexpandablearray_t *l)
        memset(l, 0, sizeof(*l));
 }
 
-// VorteX: hacked Mem_ExpandableArray_AllocRecord, it does allocate record at certain index
-void *Mem_ExpandableArray_AllocRecordAtIndex(memexpandablearray_t *l, size_t index)
-{
-       size_t j;
-       if (index >= l->numarrays)
-       {
-               if (l->numarrays == l->maxarrays)
-               {
-                       memexpandablearray_array_t *oldarrays = l->arrays;
-                       l->maxarrays = max(l->maxarrays * 2, 128);
-                       l->arrays = (memexpandablearray_array_t*) Mem_Alloc(l->mempool, l->maxarrays * sizeof(*l->arrays));
-                       if (oldarrays)
-                       {
-                               memcpy(l->arrays, oldarrays, l->numarrays * sizeof(*l->arrays));
-                               Mem_Free(oldarrays);
-                       }
-               }
-               l->arrays[index].numflaggedrecords = 0;
-               l->arrays[index].data = (unsigned char *) Mem_Alloc(l->mempool, (l->recordsize + 1) * l->numrecordsperarray);
-               l->arrays[index].allocflags = l->arrays[index].data + l->recordsize * l->numrecordsperarray;
-               l->numarrays++;
-       }
-       if (l->arrays[index].numflaggedrecords < l->numrecordsperarray)
-       {
-               for (j = 0;j < l->numrecordsperarray;j++)
-               {
-                       if (!l->arrays[index].allocflags[j])
-                       {
-                               l->arrays[index].allocflags[j] = true;
-                               l->arrays[index].numflaggedrecords++;
-                               memset(l->arrays[index].data + l->recordsize * j, 0, l->recordsize);
-                               return (void *)(l->arrays[index].data + l->recordsize * j);
-                       }
-               }
-       }
-       return NULL;
-}
-
 void *Mem_ExpandableArray_AllocRecord(memexpandablearray_t *l)
 {
        size_t i, j;
diff --git a/zone.h b/zone.h
index 065f1c0..6caa039 100644 (file)
--- a/zone.h
+++ b/zone.h
@@ -122,7 +122,6 @@ memexpandablearray_t;
 void Mem_ExpandableArray_NewArray(memexpandablearray_t *l, mempool_t *mempool, size_t recordsize, int numrecordsperarray);
 void Mem_ExpandableArray_FreeArray(memexpandablearray_t *l);
 void *Mem_ExpandableArray_AllocRecord(memexpandablearray_t *l);
-void *Mem_ExpandableArray_AllocRecordAtIndex(memexpandablearray_t *l, size_t index);
 void Mem_ExpandableArray_FreeRecord(memexpandablearray_t *l, void *record);
 size_t Mem_ExpandableArray_IndexRange(const memexpandablearray_t *l) DP_FUNC_PURE;
 void *Mem_ExpandableArray_RecordAtIndex(const memexpandablearray_t *l, size_t index) DP_FUNC_PURE;