001 #include "Studio.HC"; 002 U64 SerReadU64(U8 **_ptr) { 003 U64 r=(*_ptr)[0](U64); 004 *_ptr+=8; 005 return r; 006 } 007 U64 SerReadU8(U8 **_ptr) { 008 U64 r=(*_ptr)[0]; 009 *_ptr+=1; 010 return r; 011 } 012 U8 *SerReadStr(U8 *to,U8 **_ptr) { 013 U8 *ptr=*_ptr; 014 I64 l=StrLen(ptr); 015 MemCpy(to,ptr,l+1); 016 *_ptr=ptr+l+1; 017 return ptr; 018 } 019 U0 SerWriteU64(CU8Set *s,U64 f) { 020 U8SetAddBytes(s,&f,8); 021 } 022 U0 SerWriteF64(CU8Set *s,F64 f) { 023 U8SetAddBytes(s,&f,8); 024 } 025 U0 SerWriteU8(CU8Set *s,U8 f) { 026 U8SetAddBytes(s,&f,1); 027 } 028 U0 SerWriteStr(CU8Set *s,U8 *str) { 029 U8SetAddBytes(s,str,StrLen(str)+1); 030 } 031 CFrogThing *LoadThing0(U8 **_str,U8 *_member=NULL) { 032 CFrogThing *ret=FROG_SMALL_NIL,*tmp; 033 CI64Set *init_list=FramePtr("STInitList"); 034 U8 member[STR_LEN],cls[STR_LEN],dummy[STR_LEN]; 035 U8 *member_ptr=member,*cls_ptr=cls; 036 F64 num; 037 I64 inum,ch,ptr; 038 again: 039 ch=SerReadU8(_str); 040 if(ch=='^') { 041 ptr=SerReadU64(_str); 042 SerReadStr(member,_str); 043 if(_member) StrCpy(_member,member); 044 StrPrint(member,"PTR.%d",ptr); 045 if(!FramePtr(member)) { 046 //Nroot here,Pointers are first defined then used as pointers in SaveDefacto. 047 //You(should) never reach here 048 if(!(ptr&0x7)) 049 PrintI("internalWTF(undef pointer)",ptr); 050 else 051 ret=ptr; 052 } else if(ptr) 053 ret=FramePtr(member); 054 if(**_str=='.') _str[0]++; 055 goto en; 056 } 057 if(ch=='-') { 058 ptr=SerReadU64(_str); 059 SerReadStr(member,_str); 060 SerReadStr(cls,_str); 061 if(_member) StrCpy(_member,member); 062 if(!StrCmp(cls,"CFrogDictionary")) { 063 ret=ConstructThing("CFrogDictionary"); 064 while(**_str!='.') { 065 tmp=LoadThing0(_str,member); 066 CallScript("at:put:",ret,FrogStrNew(member),tmp); 067 } 068 StrPrint(dummy,"PTR.%d",ptr); 069 FramePtrAdd(dummy,ret); 070 } else if(!StrCmp(cls,"CFrogSymbol")&&member[0]=='#') { 071 FrogSymbol(member+1)->value=LoadThing0(_str,dummy); 072 } else if(!StrCmp(cls,"CFrogNum")) { 073 inum=SerReadU64(_str); 074 ret=FrogNumNew(inum(F64)); 075 } else if(!StrCmp(cls,"CFrogChr")) { 076 inum=SerReadU8(_str); 077 ret=FrogChrNew(inum); 078 } else if(!StrCmp(cls,"CFrogClass")) { 079 SerReadStr(cls_ptr,_str); 080 ret=FrogClassNew(NameToUniverseNumber(cls)); 081 } else if(!StrCmp(cls,"CFrogArray")) { 082 inum=SerReadU64(_str); 083 ret=FrogArrayNew; 084 StrPrint(dummy,"PTR.%d",ptr); 085 FramePtrAdd(dummy,ret); 086 while(--inum>=0) { 087 I64SetAdd(ret(CFrogArray*)->items,LoadThing0(_str)); 088 } 089 } else if(!StrCmp(cls,"CFrogStr")) { 090 ret=FrogStrNew(""); 091 StrPrint(dummy,"PTR.%d",ptr); 092 FramePtrAdd(dummy,ret); 093 inum=SerReadU64(_str); 094 U8SetAddBytes(ret(CFrogStr*)->items,*_str,inum); 095 *_str+=inum; 096 } else { 097 ret=ConstructThing(cls); 098 StrPrint(dummy,"PTR.%d",ptr); 099 FramePtrAdd(dummy,ret); 100 if(ret) CallScript("beforeRestore",ret); 101 while(**_str&&**_str!='.') { 102 tmp=LoadThing0(_str,member); 103 if(ret&&tmp) SetClassMemberVal(ret,member,tmp); 104 } 105 } 106 if(**_str=='.') _str[0]++; 107 } else if(**_str) { 108 } 109 I64SetAdd(init_list,ret); 110 en: 111 return ret; 112 } 113 CFrogThing *RestoreThing0(U8 *s) { 114 CI64Set *init_list=I64SetNew; 115 CHashTable *table=HashTableNew(0x100); 116 table->next=Fs->hash_table; 117 Fs->hash_table=table; 118 FramePtrAdd("STInitList",init_list); 119 I64 cnt; 120 U8 *s2=s; 121 gc_lock_cnt++; 122 CFrogThing *r=LoadThing0(&s2); 123 gc_lock_cnt--; 124 cnt=init_list->cnt; 125 while(--cnt>=0) { 126 CallScript("afterRestore",init_list->body[cnt]); 127 } 128 Fs->hash_table=table->next; 129 HashTableDel(table); 130 I64SetDel(init_list); 131 FramePtrDel(init_list); 132 return r; 133 } 134 U0 SaveDefacto0(CU8Set *doc,U8 *str,CFrogThing *have,I64 depth=1,CI64Set *save_list) { 135 if(I64SetHas(save_list,have)) { 136 //Pointer 137 SerWriteU8(doc,'^'); 138 SerWriteU64(doc,have); 139 SerWriteStr(doc,str); 140 SerWriteU8(doc,'.'); 141 return; 142 } 143 SerWriteU8(doc,'-'); 144 if(!(have&1)) //Dont save primtive types 145 I64SetAdd(save_list,have); 146 if(depth<=0) return; 147 gc_lock_cnt++; 148 I64 cnt,val,idx,force_ser; 149 F64 fval; 150 U8 *ptr,buf[STR_LEN]; 151 CHashClass *cls; 152 CMemberLst *mlst; 153 CHashTable *dtab; 154 CHashGeneric *dtab_e; 155 CFrogThing *as,**array_body,dummy; 156 CallScript("beforeSave",have); 157 if(ThingHasClass(have,"CFrogSymbol")) { 158 SerWriteU64(doc,have); 159 SerWriteU8(doc,'#'); 160 SerWriteStr(doc,have(CFrogSymbol*)->name); 161 SerWriteStr(doc,"CFrogSymbol"); 162 SaveDefacto0(doc,"value",have(CFrogSymbol*)->value,depth+1,save_list); 163 SerWriteU8(doc,'.'); 164 } else if(ThingHasClass(have,"CFrogNum")) { 165 SerWriteU64(doc,0); 166 SerWriteStr(doc,str); 167 SerWriteStr(doc,"CFrogNum"); 168 SerWriteF64(doc,AsF64(have)); 169 SerWriteU8(doc,'.'); 170 } else if(ThingHasClass(have,"CFrogUndefined")) { 171 nil: 172 SerWriteU64(doc,0); 173 SerWriteStr(doc,str); 174 SerWriteStr(doc,"CFrogUndefined"); 175 SerWriteU8(doc,'.'); 176 } else if(ThingHasClass(have,"CFrogChr")) { 177 SerWriteU64(doc,0); 178 SerWriteStr(doc,str); 179 SerWriteStr(doc,"CFrogChr"); 180 SerWriteU8(doc,AsChar(have)); 181 SerWriteU8(doc,'.'); 182 } else if(ThingHasClass(have,"CFrogDictionary")) { 183 dtab=have(CFrogDictionary*)->t; 184 cnt=dtab->mask+1; 185 SerWriteU64(doc,have); 186 SerWriteStr(doc,str); 187 SerWriteStr(doc,"CFrogDictionary"); 188 for(idx=0;idx!=cnt;idx++) { 189 for(dtab_e=dtab->body[idx];dtab_e;dtab_e=dtab_e->next) { 190 SaveDefacto0(doc,dtab_e->str,dtab_e->user_data1,depth+1,save_list); 191 } 192 } 193 SerWriteU8(doc,'.'); 194 } else if(ThingHasClass(have,"CFrogClass")) { 195 SerWriteU64(doc,have); 196 SerWriteStr(doc,str); 197 SerWriteStr(doc,"CFrogClass"); 198 SerWriteStr(doc,UniverseNumberToName(have>>16)); 199 SerWriteU8(doc,'.'); 200 } else if(ThingHasClass(have,"CFrogBlock")) { 201 goto nil; 202 } else if(ThingHasClass(have,"CFrogStr")) { 203 SerWriteU64(doc,have); 204 SerWriteStr(doc,str); 205 SerWriteStr(doc,"CFrogStr"); 206 SerWriteU64(doc,have(CFrogStr*)->items->cnt); 207 U8SetAddBytes(doc,have(CFrogStr*)->items->body,have(CFrogStr*)->items->cnt); 208 SerWriteU8(doc,'.'); 209 } else if(ThingHasClass(have,"CFrogArray")) { 210 SerWriteU64(doc,have); 211 SerWriteStr(doc,str); 212 SerWriteStr(doc,"CFrogArray"); 213 SerWriteU64(doc,have(CFrogArray*)->items->cnt); 214 cnt=have(CFrogArray*)->items->cnt; 215 array_body=have(CFrogArray*)->items->body; 216 for(idx=0;idx!=cnt;idx++) { 217 StrPrint(buf,"%X",idx); 218 SaveDefacto0(doc,buf,array_body[idx],depth+1,save_list); 219 } 220 SerWriteU8(doc,'.'); 221 } else { 222 SerWriteU64(doc,have); 223 SerWriteStr(doc,str); 224 SerWriteStr(doc,FrogThingClassName(have)); 225 cls=HashFind(FrogThingClassName(have),frog_mem_task->hash_table,HTT_CLASS); 226 MemSet(&dummy,0,sizeof CFrogThing); 227 while(cls) { 228 if(!StrCmp("CFrogThing",cls->str)) 229 break; 230 mlst=cls->member_lst_and_root; 231 while(mlst) { 232 if(mlst->member_class->ptr_stars_cnt==1) { 233 dummy.universe_class_idx=UniverseAddClass(mlst->member_class[-1].str); 234 if(!MemberMetaFind("no_serialize",mlst)) { 235 force_ser=ToBool(MemberMetaFind("recur_serialize",mlst)); 236 if(ThingHasClass(&dummy,"CFrogThing")) { 237 val=GetClassMemberValI64(have,mlst->str); 238 SaveDefacto0(doc,mlst->str,val,depth+force_ser,save_list); 239 } 240 } 241 } else if(!mlst->member_class->ptr_stars_cnt) { 242 SaveDefacto0(doc,mlst->str,FrogNumNew(GetClassMemberValF64(have,mlst->str)),depth+force_ser,save_list); 243 } 244 mlst=mlst->next; 245 } 246 cls=cls->base_class; 247 } 248 SerWriteU8(doc,'.'); 249 } 250 gc_lock_cnt--; 251 } 252 CFrogStr *SaveThing(CFrogStr *t,I64 *argv,I64 argc) { 253 CU8Set *set =U8SetNew(frog_mem_task); 254 CI64Set *save_list=I64SetNew; 255 SaveDefacto0(set,"",t,,save_list); 256 I64SetDel(save_list); 257 t=FrogStrNew(""); 258 U8SetDel(t->items); 259 t->items=set; 260 return t; 261 } 262 CFrogStr *SaveThingToSaveFile(CFrogThing *t,I64 *argv,I64 argc) { 263 U8 *name=AsString(argv[0]); 264 if(!name) return FROG_SMALL_NIL; 265 U8 *in_dir=MStrPrint("/FrogSaves/%s.DD",name); 266 if(!FileFind("/FrogSaves")) DirMk("/FrogSaves"); 267 CU8Set *doc=U8SetNew; 268 CI64Set *save_list=I64SetNew; 269 SaveDefacto0(doc,"",t,,save_list); 270 I64SetDel(save_list); 271 FileWrite(in_dir,doc->body,doc->cnt); 272 Free(in_dir); 273 U8SetDel(doc); 274 Free(name); 275 return FROG_SMALL_NIL; 276 } 277 CFrogThing *RestoreThingFromSaveFile(CFrogStr *t,I64 *argv,I64 argc) { 278 U8 *name=AsString(t); 279 if(!name) return FROG_SMALL_NIL; 280 CFrogThing *ret=FROG_SMALL_NIL; 281 U8 *in_dir=MStrPrint("/FrogSaves/%s.DD",name),*data,*d2; 282 data=FileRead(in_dir); 283 Free(name); 284 Free(in_dir); 285 if(data) { 286 ret=RestoreThing0(data); 287 Free(data); 288 } 289 return ret; 290 } 291 CFrogThing *RestoreThing(CFrogStr *t,I64 *argv,I64 argc) { 292 return RestoreThing0(t->items->body); 293 } 294 295 AddMethod("CFrogThing","saveThingToSaveFile:",&SaveThingToSaveFile); 296 AddMethod("CFrogStr","restoreThingFromSaveFile",&RestoreThingFromSaveFile); 297 AddMethod("CFrogThing","saveThing",&SaveThing); 298 AddMethod("CFrogThing","basicSaveThing",&SaveThing); 299 AddMethod("CFrogStr","restoreThing",&RestoreThing);