gwenhywfar
4.3.1
|
00001 /*************************************************************************** 00002 $RCSfile$ 00003 ------------------- 00004 cvs : $Id: stringlist.c 1067 2006-05-22 15:25:23Z christian $ 00005 begin : Thu Apr 03 2003 00006 copyright : (C) 2003 by Martin Preuss 00007 email : martin@libchipcard.de 00008 00009 *************************************************************************** 00010 * * 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU Lesser General Public * 00013 * License as published by the Free Software Foundation; either * 00014 * version 2.1 of the License, or (at your option) any later version. * 00015 * * 00016 * This library is distributed in the hope that it will be useful, * 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00019 * Lesser General Public License for more details. * 00020 * * 00021 * You should have received a copy of the GNU Lesser General Public * 00022 * License along with this library; if not, write to the Free Software * 00023 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 00024 * MA 02111-1307 USA * 00025 * * 00026 ***************************************************************************/ 00027 00028 #ifdef HAVE_CONFIG_H 00029 # include <config.h> 00030 #endif 00031 00032 #include "gwensignal_p.h" 00033 #include <gwenhywfar/misc.h> 00034 #include <gwenhywfar/debug.h> 00035 #include <gwenhywfar/inherit.h> 00036 #include <stdlib.h> 00037 #include <assert.h> 00038 #include <string.h> 00039 00040 00041 00042 GWEN_LIST2_FUNCTIONS(GWEN_SIGNAL, GWEN_Signal) 00043 GWEN_LIST2_FUNCTIONS(GWEN_SLOT, GWEN_Slot) 00044 00045 00046 GWEN_SIGNALOBJECT *GWEN_SignalObject_new(void) { 00047 GWEN_SIGNALOBJECT *so; 00048 00049 GWEN_NEW_OBJECT(GWEN_SIGNALOBJECT, so); 00050 so->signalList=GWEN_Signal_List2_new(); 00051 so->slotList=GWEN_Slot_List2_new(); 00052 00053 return so; 00054 } 00055 00056 00057 00058 void GWEN_SignalObject_free(GWEN_SIGNALOBJECT *so) { 00059 if (so) { 00060 GWEN_Slot_List2_freeAll(so->slotList); 00061 GWEN_Signal_List2_freeAll(so->signalList); 00062 GWEN_FREE_OBJECT(so); 00063 } 00064 } 00065 00066 00067 00068 uint32_t GWEN_SignalObject_MkTypeId(const char *typeName) { 00069 return GWEN_Inherit_MakeId(typeName); 00070 } 00071 00072 00073 00074 GWEN_SIGNAL *GWEN_SignalObject__findSignal(const GWEN_SIGNALOBJECT *so, 00075 const char *name, 00076 uint32_t typeId1, 00077 uint32_t typeId2) { 00078 GWEN_SIGNAL_LIST2_ITERATOR *sit; 00079 00080 assert(so); 00081 assert(name); 00082 00083 sit=GWEN_Signal_List2_First(so->signalList); 00084 if (sit) { 00085 GWEN_SIGNAL *sig; 00086 00087 sig=GWEN_Signal_List2Iterator_Data(sit); 00088 assert(sig); 00089 while(sig) { 00090 const char *s; 00091 00092 s=sig->name; 00093 assert(s); 00094 if (strcasecmp(s, name)==0 && 00095 (typeId1==0 || typeId1==sig->typeOfArg1) && 00096 (typeId2==0 || typeId2==sig->typeOfArg2)) { 00097 GWEN_Signal_List2Iterator_free(sit); 00098 return sig; 00099 } 00100 sig=GWEN_Signal_List2Iterator_Next(sit); 00101 } 00102 GWEN_Signal_List2Iterator_free(sit); 00103 } 00104 00105 return 0; 00106 } 00107 00108 00109 00110 GWEN_SIGNAL *GWEN_SignalObject_FindSignal(const GWEN_SIGNALOBJECT *so, 00111 const char *name, 00112 const char *typeOfArg1, 00113 const char *typeOfArg2) { 00114 uint32_t typeId1=0; 00115 uint32_t typeId2=0; 00116 00117 if (typeOfArg1) 00118 typeId1=GWEN_SignalObject_MkTypeId(typeOfArg1); 00119 if (typeOfArg2) 00120 typeId2=GWEN_SignalObject_MkTypeId(typeOfArg2); 00121 return GWEN_SignalObject__findSignal(so, name, typeId1, typeId2); 00122 } 00123 00124 00125 00126 GWEN_SLOT *GWEN_SignalObject__findSlot(const GWEN_SIGNALOBJECT *so, 00127 const char *name, 00128 uint32_t typeId1, 00129 uint32_t typeId2) { 00130 GWEN_SLOT_LIST2_ITERATOR *sit; 00131 00132 assert(so); 00133 assert(name); 00134 00135 sit=GWEN_Slot_List2_First(so->slotList); 00136 if (sit) { 00137 GWEN_SLOT *slot; 00138 00139 slot=GWEN_Slot_List2Iterator_Data(sit); 00140 assert(slot); 00141 while(slot) { 00142 const char *s; 00143 00144 s=slot->name; 00145 assert(s); 00146 if (strcasecmp(s, name)==0 && 00147 (typeId1==0 || typeId1==slot->typeOfArg1) && 00148 (typeId2==0 || typeId2==slot->typeOfArg2)) { 00149 GWEN_Slot_List2Iterator_free(sit); 00150 return slot; 00151 } 00152 slot=GWEN_Slot_List2Iterator_Next(sit); 00153 } 00154 GWEN_Slot_List2Iterator_free(sit); 00155 } 00156 00157 return 0; 00158 } 00159 00160 00161 00162 GWEN_SLOT *GWEN_SignalObject_FindSlot(const GWEN_SIGNALOBJECT *so, 00163 const char *name, 00164 const char *typeOfArg1, 00165 const char *typeOfArg2) { 00166 uint32_t typeId1=0; 00167 uint32_t typeId2=0; 00168 00169 if (typeOfArg1) 00170 typeId1=GWEN_SignalObject_MkTypeId(typeOfArg1); 00171 if (typeOfArg2) 00172 typeId2=GWEN_SignalObject_MkTypeId(typeOfArg2); 00173 return GWEN_SignalObject__findSlot(so, name, typeId1, typeId2); 00174 } 00175 00176 00177 00178 int GWEN_SignalObject_AddSignal(GWEN_SIGNALOBJECT *so, GWEN_SIGNAL *sig) { 00179 if (GWEN_SignalObject__findSignal(so, sig->name, 00180 sig->typeOfArg1, 00181 sig->typeOfArg2)) { 00182 DBG_ERROR(GWEN_LOGDOMAIN, 00183 "Signal \"%s\" already exists", 00184 sig->name); 00185 return GWEN_ERROR_INVALID; 00186 } 00187 00188 sig->signalObject=so; 00189 GWEN_Signal_List2_PushBack(so->signalList, sig); 00190 DBG_INFO(GWEN_LOGDOMAIN, "Added signal \"%s\"", sig->name); 00191 return 0; 00192 } 00193 00194 00195 00196 int GWEN_SignalObject_AddSlot(GWEN_SIGNALOBJECT *so, GWEN_SLOT *slot) { 00197 if (GWEN_SignalObject__findSlot(so, slot->name, 00198 slot->typeOfArg1, 00199 slot->typeOfArg2)) { 00200 DBG_ERROR(GWEN_LOGDOMAIN, 00201 "Slot \"%s\" already exists", 00202 slot->name); 00203 return GWEN_ERROR_INVALID; 00204 } 00205 slot->signalObject=so; 00206 GWEN_Slot_List2_PushBack(so->slotList, slot); 00207 DBG_INFO(GWEN_LOGDOMAIN, "Added slot \"%s\"", slot->name); 00208 return 0; 00209 } 00210 00211 00212 00213 void GWEN_SignalObject_RemoveForDerivedType(GWEN_SIGNALOBJECT *so, 00214 const char *derivedType) { 00215 uint32_t typeId=0; 00216 GWEN_SLOT_LIST2_ITERATOR *slotIt; 00217 GWEN_SIGNAL_LIST2_ITERATOR *sigIt; 00218 00219 assert(so); 00220 if (derivedType) 00221 typeId=GWEN_SignalObject_MkTypeId(derivedType); 00222 00223 slotIt=GWEN_Slot_List2_First(so->slotList); 00224 if (slotIt) { 00225 GWEN_SLOT *slot; 00226 00227 slot=GWEN_Slot_List2Iterator_Data(slotIt); 00228 assert(slot); 00229 while(slot) { 00230 const char *s; 00231 00232 s=slot->name; 00233 assert(s); 00234 if (typeId==0 || slot->derivedParentType==typeId) { 00235 GWEN_Slot_List2_Erase(so->slotList, slotIt); 00236 GWEN_Slot_free(slot); 00237 /* iterator now points to the next entry in any case (or NULL) */ 00238 slot=GWEN_Slot_List2Iterator_Data(slotIt); 00239 } 00240 else 00241 slot=GWEN_Slot_List2Iterator_Next(slotIt); 00242 } 00243 GWEN_Slot_List2Iterator_free(slotIt); 00244 } 00245 00246 sigIt=GWEN_Signal_List2_First(so->signalList); 00247 if (sigIt) { 00248 GWEN_SIGNAL *sig; 00249 00250 sig=GWEN_Signal_List2Iterator_Data(sigIt); 00251 assert(sig); 00252 while(sig) { 00253 const char *s; 00254 00255 s=sig->name; 00256 assert(s); 00257 if (typeId==0 || sig->derivedParentType==typeId) { 00258 GWEN_Signal_List2_Erase(so->signalList, sigIt); 00259 GWEN_Signal_free(sig); 00260 /* iterator now points to the next entry in any case (or NULL) */ 00261 sig=GWEN_Signal_List2Iterator_Data(sigIt); 00262 } 00263 else 00264 sig=GWEN_Signal_List2Iterator_Next(sigIt); 00265 } 00266 GWEN_Signal_List2Iterator_free(sigIt); 00267 } 00268 } 00269 00270 00271 00272 00273 00274 GWEN_SIGNAL *GWEN_Signal_new(GWEN_SIGNALOBJECT *so, 00275 const char *derivedType, 00276 const char *name, 00277 const char *typeOfArg1, 00278 const char *typeOfArg2) { 00279 GWEN_SIGNAL *sig; 00280 00281 assert(so); 00282 assert(name); 00283 GWEN_NEW_OBJECT(GWEN_SIGNAL, sig) 00284 sig->_refCount=1; 00285 sig->connectedSlots=GWEN_Slot_List2_new(); 00286 sig->name=strdup(name); 00287 if (typeOfArg1) 00288 sig->typeOfArg1=GWEN_SignalObject_MkTypeId(typeOfArg1); 00289 if (typeOfArg2) 00290 sig->typeOfArg2=GWEN_SignalObject_MkTypeId(typeOfArg2); 00291 if (derivedType) 00292 sig->derivedParentType=GWEN_SignalObject_MkTypeId(derivedType); 00293 00294 if (GWEN_SignalObject_AddSignal(so, sig)) { 00295 GWEN_Signal_free(sig); 00296 return 0; 00297 } 00298 00299 return sig; 00300 } 00301 00302 00303 00304 void GWEN_Signal_free(GWEN_SIGNAL *sig) { 00305 if (sig) { 00306 assert(sig->_refCount); 00307 if (sig->_refCount==1) { 00308 GWEN_SLOT_LIST2_ITERATOR *sit; 00309 00310 /* remove from all connected slots */ 00311 sit=GWEN_Slot_List2_First(sig->connectedSlots); 00312 if (sit) { 00313 GWEN_SLOT *slot; 00314 00315 slot=GWEN_Slot_List2Iterator_Data(sit); 00316 assert(slot); 00317 while(slot) { 00318 GWEN_SLOT *next; 00319 00320 next=GWEN_Slot_List2Iterator_Next(sit); 00321 DBG_ERROR(GWEN_LOGDOMAIN, 00322 "Disconnecting signal \"%s\" from slot \"%s\"", 00323 sig->name, slot->name); 00324 GWEN_Signal_List2_Remove(slot->connectedSignals, sig); 00325 slot=next; 00326 } 00327 GWEN_Slot_List2Iterator_free(sit); 00328 } 00329 GWEN_Slot_List2_free(sig->connectedSlots); 00330 00331 free(sig->name); 00332 sig->_refCount=0; 00333 GWEN_FREE_OBJECT(sig); 00334 } 00335 else 00336 sig->_refCount--; 00337 } 00338 } 00339 00340 00341 00342 void GWEN_Signal_Attach(GWEN_SIGNAL *sig) { 00343 assert(sig); 00344 assert(sig->_refCount); 00345 sig->_refCount++; 00346 } 00347 00348 00349 00350 GWEN_SIGNAL *GWEN_Signal__List2_freeAll_cb(GWEN_SIGNAL *sig, GWEN_UNUSED void *user_data){ 00351 GWEN_Signal_free(sig); 00352 return 0; 00353 } 00354 00355 00356 00357 void GWEN_Signal_List2_freeAll(GWEN_SIGNAL_LIST2 *slist) { 00358 GWEN_Signal_List2_ForEach(slist, GWEN_Signal__List2_freeAll_cb, 0); 00359 GWEN_Signal_List2_free(slist); 00360 } 00361 00362 00363 00364 GWEN_SIGNAL *GWEN_Signal__List2_hasSignal_cb(GWEN_SIGNAL *sig, 00365 void *user_data){ 00366 if ((void*)sig==user_data) 00367 return sig; 00368 return 0; 00369 } 00370 00371 00372 00373 int GWEN_Signal_List2_HasSignal(GWEN_SIGNAL_LIST2 *slist, 00374 const GWEN_SIGNAL *sig) { 00375 if (GWEN_Signal_List2_ForEach(slist, GWEN_Signal__List2_hasSignal_cb, 00376 (void*)sig)) 00377 return 1; 00378 return 0; 00379 } 00380 00381 00382 00383 GWEN_SIGNALOBJECT *GWEN_Signal_GetSignalObject(const GWEN_SIGNAL *sig) { 00384 assert(sig); 00385 return sig->signalObject; 00386 } 00387 00388 00389 00390 int GWEN_Signal_Connect(GWEN_SIGNAL *sig, GWEN_SLOT *slot) { 00391 assert(sig); 00392 assert(slot); 00393 if (sig->typeOfArg1!=slot->typeOfArg1) { 00394 DBG_ERROR(GWEN_LOGDOMAIN, 00395 "Signal \"%s\" and slot \"%s\" use different types for " 00396 "argument 1", 00397 sig->name, slot->name); 00398 return GWEN_ERROR_INVALID; 00399 } 00400 if (sig->typeOfArg2!=slot->typeOfArg2) { 00401 DBG_ERROR(GWEN_LOGDOMAIN, 00402 "Signal \"%s\" and slot \"%s\" use different types for " 00403 "argument 2", 00404 sig->name, slot->name); 00405 return GWEN_ERROR_INVALID; 00406 } 00407 if (GWEN_Signal_List2_HasSignal(slot->connectedSignals, sig)) { 00408 DBG_ERROR(GWEN_LOGDOMAIN, 00409 "Signal \"%s\" and slot \"%s\" already connected", 00410 sig->name, slot->name); 00411 return GWEN_ERROR_INVALID; 00412 } 00413 00414 if (GWEN_Slot_List2_HasSlot(sig->connectedSlots, slot)) { 00415 DBG_ERROR(GWEN_LOGDOMAIN, 00416 "Signal \"%s\" and slot \"%s\" already connected", 00417 sig->name, slot->name); 00418 return GWEN_ERROR_INVALID; 00419 } 00420 00421 GWEN_Signal_List2_PushBack(slot->connectedSignals, sig); 00422 GWEN_Slot_List2_PushBack(sig->connectedSlots, slot); 00423 00424 return 0; 00425 } 00426 00427 00428 00429 int GWEN_Signal_Disconnect(GWEN_SIGNAL *sig, GWEN_SLOT *slot) { 00430 assert(sig); 00431 assert(slot); 00432 if (GWEN_Signal_List2_HasSignal(slot->connectedSignals, sig)==0) { 00433 DBG_ERROR(GWEN_LOGDOMAIN, 00434 "Signal \"%s\" and slot \"%s\" are not connected", 00435 sig->name, slot->name); 00436 return GWEN_ERROR_INVALID; 00437 } 00438 00439 if (GWEN_Slot_List2_HasSlot(sig->connectedSlots, slot)==0) { 00440 DBG_ERROR(GWEN_LOGDOMAIN, 00441 "Signal \"%s\" and slot \"%s\" are not connected", 00442 sig->name, slot->name); 00443 return GWEN_ERROR_INVALID; 00444 } 00445 00446 GWEN_Signal_List2_Remove(slot->connectedSignals, sig); 00447 GWEN_Slot_List2_Remove(sig->connectedSlots, slot); 00448 00449 return 0; 00450 } 00451 00452 00453 00454 int GWEN_Signal_Emit(GWEN_SIGNAL *sig, 00455 void *pArg1, void *pArg2, int iArg3, int iArg4) { 00456 GWEN_SLOT_LIST2_ITERATOR *sit; 00457 int result=0; 00458 00459 assert(sig); 00460 sit=GWEN_Slot_List2_First(sig->connectedSlots); 00461 if (sit) { 00462 GWEN_SLOT *slot; 00463 00464 slot=GWEN_Slot_List2Iterator_Data(sit); 00465 assert(slot); 00466 while(slot) { 00467 if (slot->func) { 00468 int rv; 00469 00470 DBG_DEBUG(GWEN_LOGDOMAIN, 00471 "Sending signal \"%s\" to slot \"%s\" (%p)", 00472 sig->name, slot->name, slot); 00473 rv=slot->func(slot, slot->userData, pArg1, pArg2, iArg3, iArg4); 00474 if (rv>0) { 00475 DBG_DEBUG(GWEN_LOGDOMAIN, 00476 "Slot \"%s\" (%p) returned an error (%d)", 00477 slot->name, slot, rv); 00478 result=rv; 00479 } 00480 } 00481 slot=GWEN_Slot_List2Iterator_Next(sit); 00482 } 00483 GWEN_Slot_List2Iterator_free(sit); 00484 } 00485 00486 return result; 00487 } 00488 00489 00490 00491 00492 00493 00494 GWEN_SLOT *GWEN_Slot_new(GWEN_SIGNALOBJECT *so, 00495 const char *derivedType, 00496 const char *name, 00497 const char *typeOfArg1, 00498 const char *typeOfArg2, 00499 GWEN_SLOT_FUNCTION fn, 00500 void *userData) { 00501 GWEN_SLOT *slot; 00502 00503 assert(name); 00504 GWEN_NEW_OBJECT(GWEN_SLOT, slot) 00505 slot->_refCount=1; 00506 slot->connectedSignals=GWEN_Signal_List2_new(); 00507 slot->name=strdup(name); 00508 if (typeOfArg1) 00509 slot->typeOfArg1=GWEN_SignalObject_MkTypeId(typeOfArg1); 00510 if (typeOfArg2) 00511 slot->typeOfArg2=GWEN_SignalObject_MkTypeId(typeOfArg2); 00512 if (derivedType) 00513 slot->derivedParentType=GWEN_SignalObject_MkTypeId(derivedType); 00514 slot->func=fn; 00515 slot->userData=userData; 00516 00517 if (GWEN_SignalObject_AddSlot(so, slot)) { 00518 GWEN_Slot_free(slot); 00519 return 0; 00520 } 00521 00522 return slot; 00523 } 00524 00525 00526 00527 void GWEN_Slot_free(GWEN_SLOT *slot) { 00528 if (slot) { 00529 assert(slot->_refCount); 00530 if (slot->_refCount==1) { 00531 GWEN_SIGNAL_LIST2_ITERATOR *sit; 00532 00533 /* remove from all connected signals */ 00534 sit=GWEN_Signal_List2_First(slot->connectedSignals); 00535 if (sit) { 00536 GWEN_SIGNAL *sig; 00537 00538 sig=GWEN_Signal_List2Iterator_Data(sit); 00539 assert(sig); 00540 while(sig) { 00541 DBG_ERROR(GWEN_LOGDOMAIN, 00542 "Disconnecting slot \"%s\" from signal \"%s\"", 00543 slot->name, sig->name); 00544 GWEN_Slot_List2_Remove(sig->connectedSlots, slot); 00545 sig=GWEN_Signal_List2Iterator_Next(sit); 00546 } 00547 GWEN_Signal_List2Iterator_free(sit); 00548 } 00549 GWEN_Signal_List2_free(slot->connectedSignals); 00550 00551 free(slot->name); 00552 slot->_refCount=0; 00553 GWEN_FREE_OBJECT(slot); 00554 } 00555 else 00556 slot->_refCount--; 00557 } 00558 } 00559 00560 00561 00562 void GWEN_Slot_Attach(GWEN_SLOT *slot) { 00563 assert(slot); 00564 assert(slot->_refCount); 00565 slot->_refCount++; 00566 } 00567 00568 00569 00570 GWEN_SLOT *GWEN_Slot__List2_freeAll_cb(GWEN_SLOT *slot, GWEN_UNUSED void *user_data) { 00571 GWEN_Slot_free(slot); 00572 return 0; 00573 } 00574 00575 00576 00577 void GWEN_Slot_List2_freeAll(GWEN_SLOT_LIST2 *slist) { 00578 GWEN_Slot_List2_ForEach(slist, GWEN_Slot__List2_freeAll_cb, 0); 00579 GWEN_Slot_List2_free(slist); 00580 } 00581 00582 00583 00584 GWEN_SLOT *GWEN_Slot__List2_hasSlot_cb(GWEN_SLOT *slot, 00585 void *user_data){ 00586 if ((void*)slot==user_data) 00587 return slot; 00588 return 0; 00589 } 00590 00591 00592 00593 int GWEN_Slot_List2_HasSlot(GWEN_SLOT_LIST2 *slist, 00594 const GWEN_SLOT *slot) { 00595 if (GWEN_Slot_List2_ForEach(slist, GWEN_Slot__List2_hasSlot_cb, 00596 (void*)slot)) 00597 return 1; 00598 return 0; 00599 } 00600 00601 00602 00603 GWEN_SIGNALOBJECT *GWEN_Slot_GetSignalObject(const GWEN_SLOT *slot) { 00604 assert(slot); 00605 return slot->signalObject; 00606 } 00607 00608 00609 00610 00611 00612 00613