lscript_library/lscript_alloc.cpp

Go to the documentation of this file.
00001 
00032 // #define at top of file accelerates gcc compiles
00033 // Under gcc 2.9, the manual is unclear if comments can appear above #ifndef
00034 // Under gcc 3, the manual explicitly states comments can appear above the #ifndef
00035 
00036 #include "linden_common.h"
00037 #include "lscript_alloc.h"
00038 #include "llrand.h"
00039 
00040 // supported data types
00041 
00042 //      basic types
00043 //      integer                 4 bytes of integer data
00044 //      float                   4 bytes of float data
00045 //      string data             null terminated 1 byte string
00046 //      key data                null terminated 1 byte string
00047 //      vector data             12 bytes of 3 floats
00048 //      quaternion data 16 bytes of 4 floats
00049 
00050 //      list type
00051 //      list data               4 bytes of number of entries followed by pointer
00052 
00053 //      string pointer          4 bytes of address of string data on the heap (only used in list data)
00054 //  key pointer                 4 bytes of address of key data on the heap (only used in list data)
00055 
00056 // heap format
00057 // 
00058 // 4 byte offset to next block (in bytes)
00059 // 1 byte of type of variable or empty
00060 // 2 bytes of reference count
00061 // nn bytes of data
00062 
00063 void reset_hp_to_safe_spot(const U8 *buffer)
00064 {
00065         set_register((U8 *)buffer, LREG_HP, TOP_OF_MEMORY);
00066 }
00067 
00068 // create a heap from the HR to TM
00069 BOOL lsa_create_heap(U8 *heap_start, S32 size)
00070 {
00071         LLScriptAllocEntry entry(size, LST_NULL);
00072 
00073         S32 position = 0;
00074 
00075         alloc_entry2bytestream(heap_start, position, entry);
00076 
00077         return TRUE;
00078 }
00079 
00080 S32 lsa_heap_top(U8 *heap_start, S32 maxtop)
00081 {
00082         S32 offset = 0;
00083         LLScriptAllocEntry entry;
00084         bytestream2alloc_entry(entry, heap_start, offset);
00085 
00086         while (offset + entry.mSize < maxtop)
00087         {
00088                 offset += entry.mSize;
00089                 bytestream2alloc_entry(entry, heap_start, offset);
00090         }
00091         return offset + entry.mSize;
00092 }
00093 
00094 
00095 // adding to heap
00096 //      if block is empty
00097 //              if block is at least block size + 4 larger than data
00098 //                      split block
00099 //                      insert data into first part
00100 //                      return address
00101 //              else
00102 //                      insert data into block
00103 //                      return address
00104 //      else
00105 //              if next block is >= SP 
00106 //                      set Stack-Heap collision
00107 //                      return NULL
00108 //              if next block is empty
00109 //                      merge next block with current block
00110 //                      go to start of algorithm
00111 //              else
00112 //                      move to next block
00113 //                      go to start of algorithm
00114 
00115 S32 lsa_heap_add_data(U8 *buffer, LLScriptLibData *data, S32 heapsize, BOOL b_delete)
00116 {
00117         if (get_register(buffer, LREG_FR))
00118                 return 1;
00119         LLScriptAllocEntry entry, nextentry;
00120         S32 hr = get_register(buffer, LREG_HR);
00121         S32 hp = get_register(buffer, LREG_HP);
00122         S32 current_offset, next_offset, offset = hr;
00123         S32 size = 0;
00124 
00125         switch(data->mType)
00126         {
00127         case LST_INTEGER:
00128                 size = 4;
00129                 break;
00130         case LST_FLOATINGPOINT:
00131                 size = 4;
00132                 break;
00133         case LST_KEY:
00134                 size = (S32)strlen(data->mKey) + 1;                     /*Flawfinder: ignore*/
00135                 break;
00136         case LST_STRING:
00137                 size = (S32)strlen(data->mString) + 1;          /*Flawfinder: ignore*/ 
00138                 break;
00139         case LST_LIST:
00140                 //      list data               4 bytes of number of entries followed by number of pointer
00141                 size = 4 + 4*data->getListLength();
00142                 if (data->checkForMultipleLists())
00143                 {
00144                         set_fault(buffer, LSRF_NESTING_LISTS);
00145                 }
00146                 break;
00147         case LST_VECTOR:
00148                 size = 12;
00149                 break;
00150         case LST_QUATERNION:
00151                 size = 16;
00152                 break;
00153         default:
00154                 break;
00155         }
00156 
00157         current_offset = offset;
00158         bytestream2alloc_entry(entry, buffer, offset);
00159 
00160         do
00161         {
00162                 hp = get_register(buffer, LREG_HP);
00163                 if (!entry.mType)
00164                 {
00165                         if (entry.mSize >= size + SIZEOF_SCRIPT_ALLOC_ENTRY + 4)
00166                         {
00167                                 offset = current_offset;
00168                                 lsa_split_block(buffer, offset, size, entry);
00169                                 entry.mType = data->mType;
00170                                 entry.mSize = size;
00171                                 entry.mReferenceCount = 1;
00172                                 offset = current_offset;
00173                                 alloc_entry2bytestream(buffer, offset, entry);
00174                                 lsa_insert_data(buffer, offset, data, entry, heapsize);
00175                                 hp = get_register(buffer, LREG_HP);
00176                                 S32 new_hp = current_offset + size + 2*SIZEOF_SCRIPT_ALLOC_ENTRY;
00177                                 if (new_hp >= hr + heapsize)
00178                                 {
00179                                         break;
00180                                 }
00181                                 if (new_hp > hp)
00182                                 {
00183                                         set_register(buffer, LREG_HP, new_hp);
00184                                         hp = get_register(buffer, LREG_HP);
00185                                 }
00186                                 if (b_delete)
00187                                         delete data;
00188         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00189         // and function clean up of ref counts isn't based on scope (a mistake, I know)
00190                                 if (current_offset <= hp)
00191                                         return current_offset - hr + 1;
00192                                 else
00193                                         return hp - hr + 1;
00194                         }
00195                         else if (entry.mSize >= size)
00196                         {
00197                                 entry.mType = data->mType;
00198                                 entry.mReferenceCount = 1;
00199                                 offset = current_offset;
00200                                 alloc_entry2bytestream(buffer, offset, entry);
00201                                 lsa_insert_data(buffer, offset, data, entry, heapsize);
00202                                 hp = get_register(buffer, LREG_HP);
00203                                 if (b_delete)
00204                                         delete data;
00205         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00206         // and function clean up of ref counts isn't based on scope (a mistake, I know)
00207                                 return current_offset - hr + 1;
00208                         }
00209                 }
00210                 offset += entry.mSize;
00211                 if (offset < hr + heapsize)
00212                 {
00213                         next_offset = offset;
00214                         bytestream2alloc_entry(nextentry, buffer, offset);
00215                         if (!nextentry.mType && !entry.mType)
00216                         {
00217                                 entry.mSize += nextentry.mSize + SIZEOF_SCRIPT_ALLOC_ENTRY;
00218                                 offset = current_offset;
00219                                 alloc_entry2bytestream(buffer, offset, entry);
00220                         }
00221                         else
00222                         {
00223                                 current_offset = next_offset;
00224                                 entry = nextentry;
00225                         }
00226 
00227                         // this works whether we are bumping out or coming in
00228                         S32 new_hp = current_offset + size + 2*SIZEOF_SCRIPT_ALLOC_ENTRY;
00229 
00230                         // make sure we aren't about to be stupid
00231                         if (new_hp >= hr + heapsize)
00232                         {
00233                                 break;
00234                         }
00235                         if (new_hp > hp)
00236                         {
00237                                 set_register(buffer, LREG_HP, new_hp);
00238                                 hp = get_register(buffer, LREG_HP);
00239                         }
00240                 }
00241                 else
00242                 {
00243                         break;
00244                 }
00245         } while (1);
00246         set_fault(buffer, LSRF_STACK_HEAP_COLLISION);
00247         reset_hp_to_safe_spot(buffer);
00248         if (b_delete)
00249                 delete data;
00250         return 0;
00251 }
00252 
00253 // split block
00254 //      set offset to point to new block
00255 //      set offset of new block to point to original offset - block size - data size
00256 //      set new block to empty
00257 //      set new block reference count to 0
00258 void lsa_split_block(U8 *buffer, S32 &offset, S32 size, LLScriptAllocEntry &entry)
00259 {
00260         if (get_register(buffer, LREG_FR))
00261                 return;
00262         LLScriptAllocEntry newentry;
00263 
00264         newentry.mSize = entry.mSize - SIZEOF_SCRIPT_ALLOC_ENTRY - size;
00265         entry.mSize -= newentry.mSize + SIZEOF_SCRIPT_ALLOC_ENTRY;
00266 
00267         alloc_entry2bytestream(buffer, offset, entry);
00268         S32 orig_offset = offset + size;
00269         alloc_entry2bytestream(buffer, orig_offset, newentry);
00270 }
00271 
00272 // insert data
00273 //      if data is non-list type
00274 //              set type to basic type, set reference count to 1, copy data, return address
00275 //      else
00276 //              set type to list data type, set reference count to 1
00277 //              save length of list
00278 //              for each list entry
00279 //                      insert data
00280 //                      return address
00281 
00282 void lsa_insert_data(U8 *buffer, S32 &offset, LLScriptLibData *data, LLScriptAllocEntry &entry, S32 heapsize)
00283 {
00284         if (get_register(buffer, LREG_FR))
00285                 return;
00286         if (data->mType != LST_LIST)
00287         {
00288                 switch(data->mType)
00289                 {
00290                 case LST_INTEGER:
00291                         integer2bytestream(buffer, offset, data->mInteger);
00292                         break;
00293                 case LST_FLOATINGPOINT:
00294                         float2bytestream(buffer, offset, data->mFP);
00295                         break;
00296                 case LST_KEY:
00297                         char2bytestream(buffer, offset, data->mKey);
00298                         break;
00299                 case LST_STRING:
00300                         char2bytestream(buffer, offset, data->mString);
00301                         break;
00302                 case LST_VECTOR:
00303                         vector2bytestream(buffer, offset, data->mVec);
00304                         break;
00305                 case LST_QUATERNION:
00306                         quaternion2bytestream(buffer, offset, data->mQuat);
00307                         break;
00308                 default:
00309                         break;
00310                 }
00311         }
00312         else
00313         {
00314                 // store length of list
00315                 integer2bytestream(buffer, offset, data->getListLength());
00316                 data = data->mListp;
00317                 while(data)
00318                 {
00319                         // store entry and then store address if valid
00320                         S32 address = lsa_heap_add_data(buffer, data, heapsize, FALSE);
00321                         integer2bytestream(buffer, offset, address);
00322                         data = data->mListp;
00323                 }
00324         }
00325 }
00326 
00327 S32 lsa_create_data_block(U8 **buffer, LLScriptLibData *data, S32 base_offset)
00328 {
00329         S32 offset = 0;
00330         S32 size = 0;
00331 
00332         LLScriptAllocEntry entry;
00333 
00334         if (!data)
00335         {
00336                 entry.mType = LST_NULL;
00337                 entry.mReferenceCount = 0;
00338                 entry.mSize = MAX_HEAP_SIZE;
00339                 size = SIZEOF_SCRIPT_ALLOC_ENTRY;
00340                 *buffer = new U8[size];
00341                 alloc_entry2bytestream(*buffer, offset, entry);
00342                 return size;
00343         }
00344 
00345         entry.mType = data->mType;
00346         entry.mReferenceCount = 1;
00347 
00348         if (data->mType != LST_LIST)
00349         {
00350                 if (  (data->mType != LST_STRING)
00351                         &&(data->mType != LST_KEY))
00352                 {
00353                         size = LSCRIPTDataSize[data->mType];
00354                 }
00355                 else
00356                 {
00357                         if (data->mType == LST_STRING)
00358                         {
00359                                 if (data->mString)
00360                                 {
00361                                         size = (S32)strlen(data->mString) + 1;          /*Flawfinder: ignore*/
00362                                 }
00363                                 else
00364                                 {
00365                                         size = 1;
00366                                 }
00367                         }
00368                         if (data->mType == LST_KEY)
00369                         {
00370                                 if (data->mKey)
00371                                 {
00372                                         size = (S32)strlen(data->mKey) + 1;             /*Flawfinder: ignore*/
00373                                 }
00374                                 else
00375                                 {
00376                                         size = 1;
00377                                 }
00378                         }
00379                 }
00380                 entry.mSize = size;
00381                 size += SIZEOF_SCRIPT_ALLOC_ENTRY;
00382                 *buffer = new U8[size];
00383                 alloc_entry2bytestream(*buffer, offset, entry);
00384 
00385                 switch(data->mType)
00386                 {
00387                 case LST_INTEGER:
00388                         integer2bytestream(*buffer, offset, data->mInteger);
00389                         break;
00390                 case LST_FLOATINGPOINT:
00391                         float2bytestream(*buffer, offset, data->mFP);
00392                         break;
00393                 case LST_KEY:
00394                         if (data->mKey)
00395                                 char2bytestream(*buffer, offset, data->mKey);
00396                         else
00397                                 byte2bytestream(*buffer, offset, 0);
00398                         break;
00399                 case LST_STRING:
00400                         if (data->mString)
00401                                 char2bytestream(*buffer, offset, data->mString);
00402                         else
00403                                 byte2bytestream(*buffer, offset, 0);
00404                         break;
00405                 case LST_VECTOR:
00406                         vector2bytestream(*buffer, offset, data->mVec);
00407                         break;
00408                 case LST_QUATERNION:
00409                         quaternion2bytestream(*buffer, offset, data->mQuat);
00410                         break;
00411                 default:
00412                         break;
00413                 }
00414         }
00415         else
00416         {
00417                 U8 *listbuf;
00418                 S32 length = data->getListLength();
00419                 size = 4 * length + 4;
00420                 entry.mSize = size;
00421 
00422                 size += SIZEOF_SCRIPT_ALLOC_ENTRY;
00423                 *buffer = new U8[size];
00424 
00425                 alloc_entry2bytestream(*buffer, offset, entry);
00426                 // store length of list
00427                 integer2bytestream(*buffer, offset, length);
00428                 data = data->mListp;
00429                 while(data)
00430                 {
00431         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00432         // and function clean up of ref counts isn't based on scope (a mistake, I know)
00433                         integer2bytestream(*buffer, offset, size + base_offset + 1);
00434 
00435                         S32 listsize = lsa_create_data_block(&listbuf, data, base_offset + size);
00436                         if (listsize)
00437                         {
00438                                 U8 *tbuff = new U8[size + listsize];
00439                                 if (tbuff == NULL)
00440                                 {
00441                                         llerrs << "Memory Allocation Failed" << llendl;
00442                                 }
00443                                 memcpy(tbuff, *buffer, size);   /*Flawfinder: ignore*/
00444                                 memcpy(tbuff + size, listbuf, listsize);                /*Flawfinder: ignore*/
00445                                 size += listsize;
00446                                 delete [] *buffer;
00447                                 delete [] listbuf;
00448                                 *buffer = tbuff;
00449                         }
00450                         data = data->mListp;
00451                 }
00452         }
00453         return size;
00454 }
00455 
00456 // increase reference count
00457 //      increase reference count by 1
00458 
00459 void lsa_increase_ref_count(U8 *buffer, S32 offset)
00460 {
00461         if (get_register(buffer, LREG_FR))
00462                 return;
00463         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00464         // and function clean up of ref counts isn't based on scope (a mistake, I know)
00465         offset += get_register(buffer, LREG_HR) - 1;
00466         if (  (offset < get_register(buffer, LREG_HR))
00467                 ||(offset >= get_register(buffer, LREG_HP)))
00468         {
00469                 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
00470                 return;
00471         }
00472         S32 orig_offset = offset;
00473         LLScriptAllocEntry entry;
00474         bytestream2alloc_entry(entry, buffer, offset);
00475 
00476         entry.mReferenceCount++;
00477 
00478         alloc_entry2bytestream(buffer, orig_offset, entry);
00479 }
00480 
00481 // decrease reference count
00482 //              decrease reference count by 1
00483 //              if reference count == 0
00484 //                      set type to empty
00485 
00486 void lsa_decrease_ref_count(U8 *buffer, S32 offset)
00487 {
00488         if (get_register(buffer, LREG_FR))
00489                 return;
00490         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00491         // and function clean up of ref counts isn't based on scope (a mistake, I know)
00492         offset += get_register(buffer, LREG_HR) - 1;
00493         if (  (offset < get_register(buffer, LREG_HR))
00494                 ||(offset >= get_register(buffer, LREG_HP)))
00495         {
00496                 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
00497                 return;
00498         }
00499         S32 orig_offset = offset;
00500         LLScriptAllocEntry entry;
00501         bytestream2alloc_entry(entry, buffer, offset);
00502 
00503         entry.mReferenceCount--;
00504 
00505         if (entry.mReferenceCount < 0)
00506         {
00507                 entry.mReferenceCount = 0;
00508                 set_fault(buffer, LSRF_HEAP_ERROR);
00509         }
00510         else if (!entry.mReferenceCount)
00511         {
00512                 if (entry.mType == LST_LIST)
00513                 {
00514                         S32 i, num = bytestream2integer(buffer, offset);
00515                         for (i = 0; i < num; i++)
00516                         {
00517                                 S32 list_offset = bytestream2integer(buffer, offset);
00518                                 lsa_decrease_ref_count(buffer, list_offset);
00519                         }
00520                 }
00521                 entry.mType = LST_NULL;
00522         }
00523 
00524         alloc_entry2bytestream(buffer, orig_offset, entry);
00525 }
00526 
00527 char gLSAStringRead[16384];             /*Flawfinder: ignore*/
00528 
00529 
00530 LLScriptLibData *lsa_get_data(U8 *buffer, S32 &offset, BOOL b_dec_ref)
00531 {
00532         if (get_register(buffer, LREG_FR))
00533                 return (new LLScriptLibData);
00534         S32 orig_offset = offset;
00535         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00536         // and function clean up of ref counts isn't based on scope (a mistake, I know)
00537         offset += get_register(buffer, LREG_HR) - 1;
00538         if (  (offset < get_register(buffer, LREG_HR))
00539                 ||(offset >= get_register(buffer, LREG_HP)))
00540         {
00541                 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
00542                 return (new LLScriptLibData);
00543         }
00544         LLScriptAllocEntry entry;
00545         bytestream2alloc_entry(entry, buffer, offset);
00546 
00547         LLScriptLibData *retval = new LLScriptLibData;
00548 
00549         if (!entry.mType)
00550         {
00551                 set_fault(buffer, LSRF_HEAP_ERROR);
00552                 return retval;
00553         }
00554 
00555         retval->mType = (LSCRIPTType)entry.mType;
00556         if (entry.mType != LST_LIST)
00557         {
00558                 switch(entry.mType)
00559                 {
00560                 case LST_INTEGER:
00561                         retval->mInteger = bytestream2integer(buffer, offset);
00562                         break;
00563                 case LST_FLOATINGPOINT:
00564                         retval->mFP = bytestream2float(buffer, offset);
00565                         break;
00566                 case LST_KEY:
00567                         bytestream2char(gLSAStringRead, buffer, offset);
00568                         retval->mKey = new char[strlen(gLSAStringRead) + 1];            /*Flawfinder: ignore*/
00569                         strcpy(retval->mKey, gLSAStringRead);                   /*Flawfinder: ignore*/
00570                         break;
00571                 case LST_STRING:
00572                         bytestream2char(gLSAStringRead, buffer, offset);
00573                         retval->mString = new char[strlen(gLSAStringRead) + 1];         /*Flawfinder: ignore*/
00574                         strcpy(retval->mString, gLSAStringRead);                        /*Flawfinder: ignore*/
00575                         break;
00576                 case LST_VECTOR:
00577                         bytestream2vector(retval->mVec, buffer, offset);
00578                         break;
00579                 case LST_QUATERNION:
00580                         bytestream2quaternion(retval->mQuat, buffer, offset);
00581                         break;
00582                 default:
00583                         break;
00584                 }
00585         }
00586         else
00587         {
00588                 // get length of list
00589                 S32 i, length = bytestream2integer(buffer, offset);
00590                 LLScriptLibData *tip = retval;
00591 
00592                 for (i = 0; i < length; i++)
00593                 {
00594                         S32 address = bytestream2integer(buffer, offset);
00595                         tip->mListp = lsa_get_data(buffer, address, FALSE);
00596                         tip = tip->mListp;
00597                 }
00598         }
00599         if (retval->checkForMultipleLists())
00600         {
00601                 set_fault(buffer, LSRF_NESTING_LISTS);
00602         }
00603         if (b_dec_ref)
00604         {
00605                 lsa_decrease_ref_count(buffer, orig_offset);
00606         }
00607         return retval;
00608 }
00609 
00610 LLScriptLibData *lsa_get_list_ptr(U8 *buffer, S32 &offset, BOOL b_dec_ref)
00611 {
00612         if (get_register(buffer, LREG_FR))
00613                 return (new LLScriptLibData);
00614         S32 orig_offset = offset;
00615         // this bit of nastiness is to get around that code paths to local variables can result in lack of initialization
00616         // and function clean up of ref counts isn't based on scope (a mistake, I know)
00617         offset += get_register(buffer, LREG_HR) - 1;
00618         if (  (offset < get_register(buffer, LREG_HR))
00619                 ||(offset >= get_register(buffer, LREG_HP)))
00620         {
00621                 set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
00622                 return (new LLScriptLibData);
00623         }
00624         LLScriptAllocEntry entry;
00625         bytestream2alloc_entry(entry, buffer, offset);
00626 
00627         if (!entry.mType)
00628         {
00629                 set_fault(buffer, LSRF_HEAP_ERROR);
00630                 return NULL;
00631         }
00632 
00633         LLScriptLibData base, *tip = &base;
00634 
00635         if (entry.mType != LST_LIST)
00636         {
00637                 return NULL;
00638         }
00639         else
00640         {
00641                 // get length of list
00642                 S32 i, length = bytestream2integer(buffer, offset);
00643 
00644                 for (i = 0; i < length; i++)
00645                 {
00646                         S32 address = bytestream2integer(buffer, offset);
00647                         tip->mListp = lsa_get_data(buffer, address, FALSE);
00648                         tip = tip->mListp;
00649                 }
00650         }
00651         if (b_dec_ref)
00652         {
00653                 lsa_decrease_ref_count(buffer, orig_offset);
00654         }
00655         tip = base.mListp;
00656         base.mListp = NULL;
00657         return tip;
00658 }
00659 
00660 S32 lsa_cat_strings(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize)
00661 {
00662         if (get_register(buffer, LREG_FR))
00663                 return 0;
00664         LLScriptLibData *string1;
00665         LLScriptLibData *string2;
00666         if (offset1 != offset2)
00667         {
00668                 string1 = lsa_get_data(buffer, offset1, TRUE);
00669                 string2 = lsa_get_data(buffer, offset2, TRUE);
00670         }
00671         else
00672         {
00673                 string1 = lsa_get_data(buffer, offset1, TRUE);
00674                 string2 = lsa_get_data(buffer, offset2, TRUE);
00675         }
00676 
00677         if (  (!string1)
00678                 ||(!string2))
00679         {
00680                 set_fault(buffer, LSRF_HEAP_ERROR);
00681                 delete string1;
00682                 delete string2;
00683                 return 0;
00684         }
00685 
00686         char *test1 = NULL, *test2 = NULL;
00687 
00688         if (string1->mType == LST_STRING)
00689         {
00690                 test1 = string1->mString;
00691         }
00692         else if (string1->mType == LST_KEY)
00693         {
00694                 test1 = string1->mKey;
00695         }
00696         if (string2->mType == LST_STRING)
00697         {
00698                 test2 = string2->mString;
00699         }
00700         else if (string2->mType == LST_KEY)
00701         {
00702                 test2 = string2->mKey;
00703         }
00704 
00705         if (  (!test1)
00706                 ||(!test2))
00707         {
00708                 set_fault(buffer, LSRF_HEAP_ERROR);
00709                 delete string1;
00710                 delete string2;
00711                 return 0;
00712         }
00713 
00714         S32 size = (S32)strlen(test1) + (S32)strlen(test2) + 1;                 /*Flawfinder: ignore*/
00715 
00716         LLScriptLibData *string3 = new LLScriptLibData;
00717         string3->mType = LST_STRING;
00718         string3->mString = new char[size];
00719         strcpy(string3->mString, test1);                        /*Flawfinder: ignore*/
00720         strcat(string3->mString, test2);                        /*Flawfinder: ignore*/
00721 
00722         delete string1;
00723         delete string2;
00724 
00725         return lsa_heap_add_data(buffer, string3, heapsize, TRUE);
00726 }
00727 
00728 S32 lsa_cmp_strings(U8 *buffer, S32 offset1, S32 offset2)
00729 {
00730         if (get_register(buffer, LREG_FR))
00731                 return 0;
00732         LLScriptLibData *string1;
00733         LLScriptLibData *string2;
00734 
00735         string1 = lsa_get_data(buffer, offset1, TRUE);
00736         string2 = lsa_get_data(buffer, offset2, TRUE);
00737         
00738         if (  (!string1)
00739                 ||(!string2))
00740         {
00741                 set_fault(buffer, LSRF_HEAP_ERROR);
00742                 delete string1;
00743                 delete string2;
00744                 return 0;
00745         }
00746 
00747         char *test1 = NULL, *test2 = NULL;
00748 
00749         if (string1->mType == LST_STRING)
00750         {
00751                 test1 = string1->mString;
00752         }
00753         else if (string1->mType == LST_KEY)
00754         {
00755                 test1 = string1->mKey;
00756         }
00757         if (string2->mType == LST_STRING)
00758         {
00759                 test2 = string2->mString;
00760         }
00761         else if (string2->mType == LST_KEY)
00762         {
00763                 test2 = string2->mKey;
00764         }
00765 
00766         if (  (!test1)
00767                 ||(!test2))
00768         {
00769                 set_fault(buffer, LSRF_HEAP_ERROR);
00770                 delete string1;
00771                 delete string2;
00772                 return 0;
00773         }
00774         S32 retval = strcmp(test1, test2);
00775 
00776         delete string1;
00777         delete string2;
00778 
00779         return retval;
00780 }
00781 
00782 void lsa_print_heap(U8 *buffer)
00783 {
00784         S32                             offset = get_register(buffer, LREG_HR);
00785         S32                             readoffset;
00786         S32                             ivalue;
00787         F32                             fpvalue;
00788         LLVector3               vvalue;
00789         LLQuaternion    qvalue;
00790         char                    string[4096];           /*Flawfinder: ignore*/
00791 
00792         LLScriptAllocEntry entry;
00793 
00794         bytestream2alloc_entry(entry, buffer, offset);
00795 
00796         printf("HP: [0x%X]\n", get_register(buffer, LREG_HP));
00797         printf("==========\n");
00798 
00799         while (offset + entry.mSize < MAX_HEAP_SIZE)
00800         {
00801                 printf("[0x%X] ", offset);
00802                 printf("%s ", LSCRIPTTypeNames[entry.mType]);
00803                 printf("Ref Count: %d ", entry.mReferenceCount);
00804                 printf("Size: %d = ", entry.mSize);
00805 
00806                 readoffset = offset;
00807 
00808                 switch(entry.mType)
00809                 {
00810                 case LST_INTEGER:
00811                         ivalue = bytestream2integer(buffer, readoffset);
00812                         printf("%d\n", ivalue);
00813                         break;
00814                 case LST_FLOATINGPOINT:
00815                         fpvalue = bytestream2float(buffer, readoffset);
00816                         printf("%f\n", fpvalue);
00817                         break;
00818                 case LST_STRING:
00819                         bytestream2char(string, buffer, readoffset);
00820                         printf("%s\n", string);
00821                         break;
00822                 case LST_KEY:
00823                         bytestream2char(string, buffer, readoffset);
00824                         printf("%s\n", string);
00825                         break;
00826                 case LST_VECTOR:
00827                         bytestream2vector(vvalue, buffer, readoffset);
00828                         printf("< %f, %f, %f >\n", vvalue.mV[VX], vvalue.mV[VY], vvalue.mV[VZ]);
00829                         break;
00830                 case LST_QUATERNION:
00831                         bytestream2quaternion(qvalue, buffer, readoffset);
00832                         printf("< %f, %f, %f, %f >\n", qvalue.mQ[VX], qvalue.mQ[VY], qvalue.mQ[VZ], qvalue.mQ[VS]);
00833                         break;
00834                 case LST_LIST:
00835                         ivalue = bytestream2integer(buffer, readoffset);
00836                         printf("%d\n", ivalue);
00837                         break;
00838                 default:
00839                         printf("\n");
00840                         break;
00841                 }
00842                 offset += entry.mSize;
00843                 bytestream2alloc_entry(entry, buffer, offset);
00844         }
00845         printf("[0x%X] ", offset);
00846         printf("%s ", LSCRIPTTypeNames[entry.mType]);
00847         printf("Ref Count: %d ", entry.mReferenceCount);
00848         printf("Size: %d\n", entry.mSize);
00849         printf("==========\n");
00850 }
00851 
00852 void lsa_fprint_heap(U8 *buffer, FILE *fp)
00853 {
00854         S32                             offset = get_register(buffer, LREG_HR);
00855         S32                             readoffset;
00856         S32                             ivalue;
00857         F32                             fpvalue;
00858         LLVector3               vvalue;
00859         LLQuaternion    qvalue;
00860         char                    string[4096];           /*Flawfinder: ignore*/
00861 
00862         LLScriptAllocEntry entry;
00863 
00864         bytestream2alloc_entry(entry, buffer, offset);
00865 
00866         while (offset + entry.mSize < MAX_HEAP_SIZE)
00867         {
00868                 fprintf(fp, "[0x%X] ", offset);
00869                 fprintf(fp, "%s ", LSCRIPTTypeNames[entry.mType]);
00870                 fprintf(fp, "Ref Count: %d ", entry.mReferenceCount);
00871                 fprintf(fp, "Size: %d = ", entry.mSize);
00872 
00873                 readoffset = offset;
00874 
00875                 switch(entry.mType)
00876                 {
00877                 case LST_INTEGER:
00878                         ivalue = bytestream2integer(buffer, readoffset);
00879                         fprintf(fp, "%d\n", ivalue);
00880                         break;
00881                 case LST_FLOATINGPOINT:
00882                         fpvalue = bytestream2float(buffer, readoffset);
00883                         fprintf(fp, "%f\n", fpvalue);
00884                         break;
00885                 case LST_STRING:
00886                         bytestream2char(string, buffer, readoffset);
00887                         fprintf(fp, "%s\n", string);
00888                         break;
00889                 case LST_KEY:
00890                         bytestream2char(string, buffer, readoffset);
00891                         fprintf(fp, "%s\n", string);
00892                         break;
00893                 case LST_VECTOR:
00894                         bytestream2vector(vvalue, buffer, readoffset);
00895                         fprintf(fp, "< %f, %f, %f >\n", vvalue.mV[VX], vvalue.mV[VY], vvalue.mV[VZ]);
00896                         break;
00897                 case LST_QUATERNION:
00898                         bytestream2quaternion(qvalue, buffer, readoffset);
00899                         fprintf(fp, "< %f, %f, %f, %f >\n", qvalue.mQ[VX], qvalue.mQ[VY], qvalue.mQ[VZ], qvalue.mQ[VS]);
00900                         break;
00901                 case LST_LIST:
00902                         ivalue = bytestream2integer(buffer, readoffset);
00903                         fprintf(fp, "%d\n", ivalue);
00904                         break;
00905                 default:
00906                         fprintf(fp, "\n");
00907                         break;
00908                 }
00909                 offset += entry.mSize;
00910                 bytestream2alloc_entry(entry, buffer, offset);
00911         }
00912         fprintf(fp, "[0x%X] ", offset);
00913         fprintf(fp, "%s ", LSCRIPTTypeNames[entry.mType]);
00914         fprintf(fp, "Ref Count: %d ", entry.mReferenceCount);
00915         fprintf(fp, "Size: %d", entry.mSize);
00916         fprintf(fp, "\n");
00917 }
00918 
00919 S32 lsa_cat_lists(U8 *buffer, S32 offset1, S32 offset2, S32 heapsize)
00920 {
00921         if (get_register(buffer, LREG_FR))
00922                 return 0;
00923         LLScriptLibData *list1;
00924         LLScriptLibData *list2;
00925         if (offset1 != offset2)
00926         {
00927                 list1 = lsa_get_data(buffer, offset1, TRUE);
00928                 list2 = lsa_get_data(buffer, offset2, TRUE);
00929         }
00930         else
00931         {
00932                 list1 = lsa_get_data(buffer, offset1, TRUE);
00933                 list2 = lsa_get_data(buffer, offset2, TRUE);
00934         }
00935 
00936         if (  (!list1)
00937                 ||(!list2))
00938         {
00939                 set_fault(buffer, LSRF_HEAP_ERROR);
00940                 delete list1;
00941                 delete list2;
00942                 return 0;
00943         }
00944 
00945         if (  (list1->mType != LST_LIST)
00946                 ||(list2->mType != LST_LIST))
00947         {
00948                 set_fault(buffer, LSRF_HEAP_ERROR);
00949                 delete list1;
00950                 delete list2;
00951                 return 0;
00952         }
00953 
00954         LLScriptLibData *runner = list1;
00955 
00956         while (runner->mListp)
00957         {
00958                 runner = runner->mListp;
00959         }
00960 
00961         runner->mListp = list2->mListp;
00962 
00963         list2->mListp = NULL;
00964 
00965         delete list2;
00966 
00967         return lsa_heap_add_data(buffer, list1, heapsize, TRUE);
00968 }
00969 
00970 
00971 S32 lsa_cmp_lists(U8 *buffer, S32 offset1, S32 offset2)
00972 {
00973         if (get_register(buffer, LREG_FR))
00974                 return 0;
00975         LLScriptLibData *list1;
00976         LLScriptLibData *list2;
00977         if (offset1 != offset2)
00978         {
00979                 list1 = lsa_get_data(buffer, offset1, TRUE);
00980                 list2 = lsa_get_data(buffer, offset2, TRUE);
00981         }
00982         else
00983         {
00984                 list1 = lsa_get_data(buffer, offset1, FALSE);
00985                 list2 = lsa_get_data(buffer, offset2, TRUE);
00986         }
00987 
00988         if (  (!list1)
00989                 ||(!list2))
00990         {
00991                 set_fault(buffer, LSRF_HEAP_ERROR);
00992                 delete list1;
00993                 delete list2;
00994                 return 0;
00995         }
00996 
00997         if (  (list1->mType != LST_LIST)
00998                 ||(list2->mType != LST_LIST))
00999         {
01000                 set_fault(buffer, LSRF_HEAP_ERROR);
01001                 delete list1;
01002                 delete list2;
01003                 return 0;
01004         }
01005 
01006         S32 length1 = list1->getListLength();
01007         S32 length2 = list2->getListLength();
01008         delete list1;
01009         delete list2;
01010         return length1 - length2;
01011 }
01012 
01013 
01014 S32 lsa_preadd_lists(U8 *buffer, LLScriptLibData *data, S32 offset2, S32 heapsize)
01015 {
01016         if (get_register(buffer, LREG_FR))
01017                 return 0;
01018         LLScriptLibData *list2 = lsa_get_data(buffer, offset2, TRUE);
01019 
01020         if (!list2)
01021         {
01022                 set_fault(buffer, LSRF_HEAP_ERROR);
01023                 delete list2;
01024                 return 0;
01025         }
01026 
01027         if (list2->mType != LST_LIST)
01028         {
01029                 set_fault(buffer, LSRF_HEAP_ERROR);
01030                 delete list2;
01031                 return 0;
01032         }
01033 
01034         LLScriptLibData *runner = data->mListp;
01035 
01036         while (runner->mListp)
01037         {
01038                 runner = runner->mListp;
01039         }
01040 
01041 
01042         runner->mListp = list2->mListp;
01043         list2->mListp = data->mListp;
01044 
01045         return lsa_heap_add_data(buffer, list2, heapsize, TRUE);
01046 }
01047 
01048 
01049 S32 lsa_postadd_lists(U8 *buffer, S32 offset1, LLScriptLibData *data, S32 heapsize)
01050 {
01051         if (get_register(buffer, LREG_FR))
01052                 return 0;
01053         LLScriptLibData *list1 = lsa_get_data(buffer, offset1, TRUE);
01054 
01055         if (!list1)
01056         {
01057                 set_fault(buffer, LSRF_HEAP_ERROR);
01058                 delete list1;
01059                 return 0;
01060         }
01061 
01062         if (list1->mType != LST_LIST)
01063         {
01064                 set_fault(buffer, LSRF_HEAP_ERROR);
01065                 delete list1;
01066                 return 0;
01067         }
01068 
01069         LLScriptLibData *runner = list1;
01070 
01071         while (runner->mListp)
01072         {
01073                 runner = runner->mListp;
01074         }
01075 
01076         runner->mListp = data->mListp;
01077 
01078         return lsa_heap_add_data(buffer, list1, heapsize, TRUE);
01079 }
01080 
01081 
01082 LLScriptLibData* lsa_randomize(LLScriptLibData* src, S32 stride)
01083 {
01084         S32 number = src->getListLength();
01085         if (number <= 0)
01086         {
01087                 return NULL;
01088         }
01089         if (stride <= 0)
01090         {
01091                 stride = 1;
01092         }
01093         if(number % stride)
01094         {
01095                 LLScriptLibData* retval = src->mListp;
01096                 src->mListp = NULL;
01097                 return retval;
01098         }
01099         S32 buckets = number / stride;
01100 
01101         // Copy everything into a special vector for sorting;
01102         std::vector<LLScriptLibData*> sort_array;
01103         sort_array.reserve(number);
01104         LLScriptLibData* temp = src->mListp;
01105         while(temp)
01106         {
01107                 sort_array.push_back(temp);
01108                 temp = temp->mListp;
01109         }
01110 
01111         // We cannot simply call random_shuffle or similar algorithm since
01112         // we need to obey the stride. So, we iterate over what we have
01113         // and swap each with a random other segment.
01114         S32 index = 0;
01115         S32 ii = 0;
01116         for(; ii < number; ii += stride)
01117         {
01118                 index = ll_rand(buckets) * stride;
01119                 for(S32 jj = 0; jj < stride; ++jj)
01120                 {
01121                         std::swap(sort_array[ii + jj], sort_array[index + jj]);
01122                 }
01123         }
01124 
01125         // copy the pointers back out
01126         ii = 1;
01127         temp = sort_array[0];
01128         while (ii < number)
01129         {
01130                 temp->mListp = sort_array[ii++];
01131                 temp = temp->mListp;
01132         }
01133         temp->mListp = NULL;
01134 
01135         src->mListp = NULL;
01136 
01137         LLScriptLibData* ret_value = sort_array[0];
01138         return ret_value;
01139 }

Generated on Thu Jul 1 06:09:49 2010 for Second Life Viewer by  doxygen 1.4.7