00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00040 #include "TclXPCOMPrivate.h"
00041 #include "nsQuickSort.h"
00042
00043
00044 typedef struct ClassInfoList {
00045 ClassInfo *cinfo;
00046 struct ClassInfoList *next;
00047 } ClassInfoList;
00048
00049
00050 typedef struct ClassInfoLookup {
00051 int iidcount;
00052 nsIID **iids;
00053 ClassInfo *cinfo;
00054 struct ClassInfoLookup *next;
00055 } ClassInfoLookup;
00056
00057
00058 typedef struct InterfaceInfoList {
00059 InterfaceInfo *iinfo;
00060 struct InterfaceInfoList *next;
00061 } InterfaceInfoList;
00062
00063
00064
00065 ClassInfoList *classInfoList;
00066 ClassInfoLookup *classLookupTable;
00067
00068
00072 void
00073 TclXPCOM_InitClassInfo(void)
00074 {
00075 classInfoList = NULL;
00076 classLookupTable = NULL;
00077 }
00078
00079
00085 InterfaceInfoList *
00086 NewInterfaceInfoList(
00087 nsIInterfaceInfo *info,
00088 InterfaceInfoList *next
00089 )
00090 {
00091 NS_PRECONDITION(info, "null pointer");
00092
00093 InterfaceInfoList *iilist;
00094 iilist = (InterfaceInfoList *)memmgr->Alloc(sizeof(InterfaceInfoList));
00095 iilist->iinfo = GetInterfaceInfo(info);
00096 iilist->next = next;
00097 return iilist;
00098 }
00099
00100
00104 void
00105 FreeInterfaceInfoList(
00106 InterfaceInfoList *iilist
00107 )
00108 {
00109 InterfaceInfoList *cur_elem, *temp;
00110
00111 NS_PRECONDITION(iilist, "null pointer");
00112
00113 for (cur_elem = iilist; cur_elem;)
00114 {
00115 temp = cur_elem;
00116 cur_elem = cur_elem->next;
00117 memmgr->Free(temp);
00118 }
00119 }
00120
00121
00127 InterfaceInfoList *
00128 GetInterfaceInfoList(
00129 nsIInterfaceInfo *info,
00130 InterfaceInfoList *list
00131 )
00132 {
00133 nsIInterfaceInfo *parent;
00134 InterfaceInfoList *iilist, *cur_elem;
00135
00136 NS_PRECONDITION(info, "null pointer");
00137
00138 for (cur_elem = list; cur_elem; cur_elem = cur_elem->next)
00139 {
00140 if (info == cur_elem->iinfo->info)
00141 {
00142 return NULL;
00143 }
00144 }
00145
00146 info->GetParent(&parent);
00147 if (parent)
00148 {
00149 iilist = GetInterfaceInfoList(parent, list);
00150 NS_RELEASE(parent);
00151 return NewInterfaceInfoList(info, iilist);
00152 } else
00153 {
00154 return NewInterfaceInfoList(info, NULL);
00155 }
00156 }
00157
00158
00164
00165
00166 ClassInfoSignature
00167 NewClassInfoSignature(
00168 int iidcount,
00169 nsIID **iids
00170 )
00171 {
00172 int i, j;
00173 nsIInterfaceInfo **infos;
00174 ClassInfoSignature signature;
00175
00176 NS_PRECONDITION((iidcount > 0), "iidcount must be greater than 0");
00177 NS_PRECONDITION(iids, "null pointer");
00178
00179 infos = (nsIInterfaceInfo **)memmgr->Alloc(sizeof(nsIInterfaceInfo *) * iidcount);
00180 memset(infos, 0, sizeof(nsIInterfaceInfo *) * iidcount);
00181
00182 signature.infocount = iidcount;
00183
00184 for (i = 0; i < iidcount; i++)
00185 {
00186 manager->GetInfoForIID(iids[i], &infos[i]);
00187 if (!infos[i])
00188 {
00189 (signature.infocount)--;
00190 }
00191 }
00192
00193 for (i = 0; i < iidcount; i++)
00194 {
00195 if (!infos[i])
00196 {
00197 continue;
00198 }
00199
00200 for (j = 0; j < iidcount; j++)
00201 {
00202 if (infos[j] && (i != j) && isInInterface(infos[i], iids[j]))
00203 {
00204 NS_RELEASE(infos[j]);
00205 infos[j] = NULL;
00206 (signature.infocount)--;
00207 }
00208 }
00209 }
00210
00211 signature.infolist = (nsIInterfaceInfo **)memmgr->Alloc(sizeof(nsIInterfaceInfo *) * signature.infocount);
00212
00213 j = 0;
00214
00215 for (i = 0; i < iidcount; i++)
00216 {
00217 if (infos[i])
00218 {
00219 signature.infolist[j] = infos[i];
00220 j++;
00221 }
00222 }
00223
00224 memmgr->Free(infos);
00225
00226 return signature;
00227 }
00228
00229
00233 void
00234 FreeClassInfoSignature(
00235 ClassInfoSignature signature
00236 )
00237 {
00238 int i;
00239
00240 NS_PRECONDITION((signature.infocount > 0), "infocount must be greater than 0");
00241 NS_PRECONDITION(signature.infolist, "null pointer");
00242
00243 for (i = 0; i < signature.infocount; i++)
00244 {
00245 NS_RELEASE(signature.infolist[i]);
00246 }
00247
00248 if (signature.infolist)
00249 {
00250 memmgr->Free(signature.infolist);
00251 }
00252 }
00253
00254
00260 InterfaceInfoList *
00261 ExpandClassInfoSignature(
00262 ClassInfoSignature signature
00263 )
00264 {
00265 int i;
00266 InterfaceInfoList *iilist, *cur_elem, *temp;
00267
00268 NS_PRECONDITION((signature.infocount > 0), "infocount must be greater than 0");
00269 NS_PRECONDITION(signature.infolist, "null pointer");
00270
00271 iilist = NULL;
00272 for (i = 0; i < signature.infocount; i++)
00273 {
00274 temp = GetInterfaceInfoList(signature.infolist[i], iilist);
00275
00276 cur_elem = temp;
00277 while (cur_elem->next)
00278 {
00279 cur_elem = cur_elem->next;
00280 }
00281
00282 cur_elem->next = iilist;
00283 iilist = temp;
00284 }
00285
00286 return iilist;
00287 }
00288
00289
00295 int
00296 ClassInfoSignaturesEqual(
00297 ClassInfoSignature signaturea,
00298 ClassInfoSignature signatureb
00299 )
00300 {
00301 NS_PRECONDITION((signaturea.infocount > 0), "infocount must be greater than 0");
00302 NS_PRECONDITION(signaturea.infolist, "null pointer");
00303 NS_PRECONDITION((signatureb.infocount > 0), "infocount must be greater than 0");
00304 NS_PRECONDITION(signatureb.infolist, "null pointer");
00305
00306 if (signaturea.infocount == signatureb.infocount)
00307 {
00308 if (!memcmp((void *)signaturea.infolist,
00309 (void *)signatureb.infolist,
00310 sizeof(nsIInterfaceInfo *) * signaturea.infocount))
00311 {
00312 return 1;
00313 }
00314 }
00315 return 0;
00316 }
00317
00318
00322 void
00323 MarkDuplicateIdentifiersInArray(
00324 int idcount,
00325 ClassIdentifierInfo *idlist
00326 )
00327 {
00328 int i, j;
00329
00330 NS_PRECONDITION((idcount >= 0), "idcount must be positive");
00331 NS_PRECONDITION(!((idcount > 0) && !idlist), "null pointer");
00332
00333 for (i = 0; i < idcount; i++)
00334 {
00335 if (idlist[i].qualified)
00336 {
00337 continue;
00338 }
00339
00340 for (j = i + 1; j < idcount; j++)
00341 {
00342 if ((idlist[i].info == idlist[j].info) || idlist[j].qualified)
00343 {
00344 continue;
00345 }
00346
00347 if (!strcmp(idlist[i].idinfo.name, idlist[j].idinfo.name))
00348 {
00349 idlist[j].qualified = 1;
00350 idlist[i].qualified = 1;
00351 }
00352 }
00353 }
00354 }
00355
00356
00360 void
00361 MarkDuplicateIdentifiersBetweenArrays(
00362 int idcounta,
00363 ClassIdentifierInfo *idlista,
00364 int idcountb,
00365 ClassIdentifierInfo *idlistb
00366 )
00367 {
00368 int i, j;
00369
00370 NS_PRECONDITION((idcounta >= 0), "idcounta must be positive");
00371 NS_PRECONDITION(!((idcounta > 0) && !idlista), "null pointer");
00372 NS_PRECONDITION((idcountb >= 0), "idcountb must be positive");
00373 NS_PRECONDITION(!((idcountb > 0) && !idlistb), "null pointer");
00374
00375 for (i = 0; i < idcounta; i++)
00376 {
00377 for (j = 0; j < idcountb; j++)
00378 {
00379 if ((idlista[i].info == idlistb[j].info) || (idlista[i].qualified && idlistb[j].qualified))
00380 {
00381 continue;
00382 }
00383
00384 if (!strcmp(idlista[i].idinfo.name, idlistb[j].idinfo.name))
00385 {
00386 idlista[i].qualified = 1;
00387 idlistb[j].qualified = 1;
00388 }
00389 }
00390 }
00391 }
00392
00393
00398 void
00399 QualifyDuplicateIdentifiers(
00400 int idcount,
00401 ClassIdentifierInfo *idlist
00402 )
00403 {
00404 int i;
00405 Tcl_Obj *identifierobj;
00406 char *identifier;
00407
00408 NS_PRECONDITION((idcount >= 0), "idcount must be positive");
00409 NS_PRECONDITION(!((idcount > 0) && !idlist), "null pointer");
00410
00411 for (i = 0; i < idcount; i++)
00412 {
00413 if (idlist[i].qualified)
00414 {
00415 identifierobj = TclXPCOM_NewIdentifierObj(idlist[i].info, idlist[i].idinfo.name);
00416 identifier = Tcl_GetString(identifierobj);
00417 idlist[i].idinfo.name = (char *)CloneMemory(identifier, sizeof(char) * (strlen(identifier) + 1));
00418 Tcl_DecrRefCount(identifierobj);
00419 }
00420 }
00421 }
00422
00423
00428 ClassIdentifierInfo *
00429 AllocateClassIdentifierInfoArray(
00430 int idcount
00431 )
00432 {
00433 ClassIdentifierInfo *cidinfo;
00434
00435 NS_PRECONDITION((idcount >= 0), "idcount must be positive");
00436
00437 if (idcount)
00438 {
00439 cidinfo = (ClassIdentifierInfo *)memmgr->Alloc(sizeof(ClassIdentifierInfo) * idcount + sizeof(char *));
00440 memset(cidinfo, 0, sizeof(ClassIdentifierInfo) * idcount + sizeof(char *));
00441 } else
00442 {
00443 cidinfo = NULL;
00444 }
00445
00446 return cidinfo;
00447 }
00448
00449
00455 ClassInfo *
00456 NewClassInfo(
00457 ClassInfoSignature signature
00458 )
00459 {
00460 PRUint16 i, methodcount, attributecount;
00461
00462 ClassInfo *cinfo;
00463 ClassIdentifierInfo *methods, *attributes;
00464 InterfaceInfoList *iilist, *cur_elem;
00465
00466 NS_PRECONDITION((signature.infocount > 0), "infocount must be greater than 0");
00467 NS_PRECONDITION(signature.infolist, "null pointer");
00468
00469 cinfo = (ClassInfo *)memmgr->Alloc(sizeof(ClassInfo));
00470
00471 iilist = ExpandClassInfoSignature(signature);
00472
00473
00474 attributecount = 0;
00475 methodcount = 0;
00476
00477 for (cur_elem = iilist; cur_elem; cur_elem = cur_elem->next)
00478 {
00479 attributecount += cur_elem->iinfo->attributecount - cur_elem->iinfo->baseattributeindex;
00480 methodcount += cur_elem->iinfo->methodcount - cur_elem->iinfo->basemethodindex;
00481 }
00482
00483
00484 attributes = AllocateClassIdentifierInfoArray(attributecount);
00485 methods = AllocateClassIdentifierInfoArray(methodcount);
00486
00487
00488 attributecount = 0;
00489 methodcount = 0;
00490
00491 for (cur_elem = iilist; cur_elem; cur_elem = cur_elem->next)
00492 {
00493 for (i = cur_elem->iinfo->baseattributeindex; i < cur_elem->iinfo->attributecount; i++)
00494 {
00495 attributes[attributecount].info = cur_elem->iinfo->info;
00496 attributes[attributecount].idinfo = cur_elem->iinfo->attributes[i];
00497 attributecount++;
00498 }
00499
00500 for (i = cur_elem->iinfo->basemethodindex; i < cur_elem->iinfo->methodcount; i++)
00501 {
00502 methods[methodcount].info = cur_elem->iinfo->info;
00503 methods[methodcount].idinfo = cur_elem->iinfo->methods[i];
00504 methodcount++;
00505 }
00506 }
00507
00508 MarkDuplicateIdentifiersInArray(attributecount, attributes);
00509 MarkDuplicateIdentifiersInArray(methodcount, methods);
00510 MarkDuplicateIdentifiersBetweenArrays(attributecount, attributes, methodcount, methods);
00511
00512 QualifyDuplicateIdentifiers(attributecount, attributes);
00513 QualifyDuplicateIdentifiers(methodcount, methods);
00514
00515 FreeInterfaceInfoList(iilist);
00516
00517
00518 cinfo->signature = signature;
00519 cinfo->methodcount = methodcount;
00520 cinfo->attributecount = attributecount;
00521 cinfo->methods = methods;
00522 cinfo->attributes = attributes;
00523
00524 return cinfo;
00525 }
00526
00527
00531 void
00532 FreeClassInfo(
00533 ClassInfo *cinfo
00534 )
00535 {
00536 PRUint16 i;
00537
00538 NS_PRECONDITION(cinfo, "null pointer");
00539
00540 FreeClassInfoSignature(cinfo->signature);
00541
00542 for (i = 0; i < cinfo->methodcount; i++)
00543 {
00544 if (cinfo->methods[i].qualified)
00545 {
00546 memmgr->Free(cinfo->methods[i].idinfo.name);
00547 }
00548 }
00549
00550 for (i = 0; i < cinfo->attributecount; i++)
00551 {
00552 if (cinfo->attributes[i].qualified)
00553 {
00554 memmgr->Free(cinfo->attributes[i].idinfo.name);
00555 }
00556 }
00557
00558 if (cinfo->methods)
00559 {
00560 memmgr->Free(cinfo->methods);
00561 }
00562
00563 if (cinfo->attributes)
00564 {
00565 memmgr->Free(cinfo->attributes);
00566 }
00567
00568 memmgr->Free(cinfo);
00569 }
00570
00571
00577 ClassInfo *
00578 FindMatchingClassInfo(
00579 ClassInfoSignature signature
00580 )
00581 {
00582 ClassInfoList *cur_elem;
00583
00584 NS_PRECONDITION((signature.infocount > 0), "infocount must be greater than 0");
00585 NS_PRECONDITION(signature.infolist, "null pointer");
00586
00587 for (cur_elem = classInfoList; cur_elem; cur_elem = cur_elem->next)
00588 {
00589 if (ClassInfoSignaturesEqual(cur_elem->cinfo->signature, signature))
00590 {
00591 return cur_elem->cinfo;
00592 }
00593 }
00594 return NULL;
00595 }
00596
00597
00603 int
00604 CompareNsIDs(
00605 const void *nsidPtra,
00606 const void *nsidPtrb,
00607 void *userdata
00608 )
00609 {
00610 return memcmp(*(void **)nsidPtra,
00611 *(void **)nsidPtrb,
00612 sizeof(nsID));
00613 }
00614
00615
00621 ClassInfo *
00622 LookupClassInfo(
00623 int iidcount,
00624 nsIID **iids
00625 )
00626 {
00627 int i, match;
00628 ClassInfoLookup *clist;
00629
00630 NS_PRECONDITION((iidcount > 0), "iidcount must be greater than 0");
00631 NS_PRECONDITION(iids, "null pointer");
00632
00633 for (clist = classLookupTable; clist; clist = clist->next)
00634 {
00635 if (clist->iidcount == iidcount)
00636 {
00637 match = 1;
00638
00639 for (i = 0; i < iidcount; i++)
00640 {
00641 if (!clist->iids[i]->Equals(*iids[i]))
00642 {
00643 match = 0;
00644 break;
00645 }
00646 }
00647
00648 if (match)
00649 {
00650 return clist->cinfo;
00651 }
00652 }
00653 }
00654
00655 return NULL;
00656 }
00657
00658
00664 ClassInfo *
00665 TclXPCOM_GetClassInfo(
00666 int iidcount,
00667 nsIID **iids
00668 )
00669 {
00670 int i;
00671 ClassInfoLookup *cinfolookup;
00672 ClassInfoList *cinfolist;
00673 ClassInfo *cinfo;
00674 nsIID **iidlist;
00675 ClassInfoSignature signature;
00676
00677 NS_PRECONDITION((iidcount > 0), "iidcount must be greater than 0");
00678 NS_PRECONDITION(iids, "null pointer");
00679
00680
00681 NS_QuickSort(iids, iidcount, sizeof(nsIID *), CompareNsIDs, NULL);
00682
00683 cinfo = LookupClassInfo(iidcount, iids);
00684
00685 if (cinfo)
00686 {
00687 return cinfo;
00688 }
00689
00690 signature = NewClassInfoSignature(iidcount, iids);
00691 cinfo = FindMatchingClassInfo(signature);
00692
00693 if (!cinfo)
00694 {
00695 cinfo = NewClassInfo(signature);
00696 cinfolist = (ClassInfoList *)memmgr->Alloc(sizeof(ClassInfoList));
00697 cinfolist->cinfo = cinfo;
00698 cinfolist->next = classInfoList;
00699 classInfoList = cinfolist;
00700 } else
00701 {
00702 FreeClassInfoSignature(signature);
00703 }
00704
00705 cinfolookup = (ClassInfoLookup *)memmgr->Alloc(sizeof(ClassInfoLookup));
00706 cinfolookup->cinfo = cinfo;
00707 cinfolookup->iidcount = iidcount;
00708
00709 iidlist = (nsIID **)memmgr->Alloc(sizeof(nsIID *) * iidcount);
00710 for (i = 0; i < iidcount; i++)
00711 {
00712 iidlist[i] = (nsIID *)CloneMemory(iids[i], sizeof(nsIID));
00713 }
00714
00715 cinfolookup->iids = iidlist;
00716 cinfolookup->next = classLookupTable;
00717 classLookupTable = cinfolookup;
00718
00719 return cinfo;
00720 }
00721
00722
00728 int
00729 TclXPCOM_GetIdentifierInfoFromClass(
00730 Tcl_Interp *interp,
00731 ClassInfo *cinfo,
00732 Tcl_Obj *identifier,
00733 int type,
00734 nsIInterfaceInfo **interfaceinfo,
00735 IdentifierInfo **idinfo
00736 )
00737 {
00738 int rv;
00739 int index;
00740 int count;
00741 char *name;
00742 ClassIdentifierInfo *cidinfos;
00743
00744 NS_PRECONDITION(interp, "null pointer");
00745 NS_PRECONDITION(cinfo, "null pointer");
00746 NS_PRECONDITION(identifier, "null pointer");
00747 NS_PRECONDITION(((type == INTERFACEINFO_METHOD) || (type == INTERFACEINFO_SETTER) || (type == INTERFACEINFO_GETTER)), "invalid identifier type code");
00748 NS_PRECONDITION(interfaceinfo, "null pointer");
00749 NS_PRECONDITION(idinfo, "null pointer");
00750
00751 switch (type)
00752 {
00753 case INTERFACEINFO_METHOD:
00754 count = cinfo->methodcount;
00755 cidinfos = cinfo->methods;
00756 name = "method";
00757 break;
00758
00759 case INTERFACEINFO_SETTER:
00760 case INTERFACEINFO_GETTER:
00761 count = cinfo->attributecount;
00762 cidinfos = cinfo->attributes;
00763 name = "attribute";
00764 break;
00765 }
00766
00767 Tcl_ResetResult(interp);
00768 if (count)
00769 {
00770 rv = Tcl_GetIndexFromObjStruct(interp, identifier, (char **)&cidinfos[0].idinfo.name, sizeof(ClassIdentifierInfo), name, 0, &index);
00771 if (rv != TCL_OK)
00772 {
00773 return rv;
00774 }
00775
00776 } else
00777 {
00778 Tcl_AppendResult(interp, "no ", name, "s in class", NULL);
00779 return TCL_ERROR;
00780 }
00781
00782 *idinfo = &cidinfos[index].idinfo;
00783 *interfaceinfo = cidinfos[index].info;
00784 return TCL_OK;
00785 }
00786