rlstate.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:15k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: rlstate.cpp,v 1.4.36.3 2004/07/09 01:48:16 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxtypes.h"
  50. #include "hxassert.h"
  51. #include "hxcom.h"
  52. #include "ihxpckts.h"
  53. #include "hxstrutl.h"
  54. #include "hxheap.h"
  55. #ifdef _DEBUG
  56. #undef HX_THIS_FILE
  57. static const char HX_THIS_FILE[] = __FILE__;
  58. #endif
  59. #include "rlstate.h"
  60. static const char WAITFORSWITCHOFF[] = "WaitForSwitchOff";
  61. static const size_t WAITFORSWITCHOFFLEN = sizeof(WAITFORSWITCHOFF) - 1;
  62. static const char ONDEPEND[] = "OnDepend";
  63. static const size_t ONDEPENDLEN = sizeof(ONDEPEND) - 1;
  64. static const char OFFDEPEND[] = "OffDepend";
  65. static const size_t OFFDEPENDLEN = sizeof(OFFDEPEND) - 1;
  66. #define NO_DEPEND_SET 0xFFFF
  67. inline void SKIP_WHITE_SPACE(char* __x)
  68. {
  69.     while (*__x == ' ' || *__x == 't' || *__x == 'n' || *__x == 'r')
  70.     {
  71. __x++;
  72.     }
  73. }
  74. /****************************************************************************
  75.  *  Method:
  76.  *    CASMRuleState::CASMRuleState
  77.  *
  78.  */
  79. CASMRuleState::CASMRuleState(UINT16 nNumRules, char* pRuleBook, 
  80.      UINT16 usBookSize)
  81. {
  82.     m_nNumRules = nNumRules;
  83.     m_bNeedSwitchOff = new BOOL[nNumRules];
  84.     m_bSubscribePending = new BOOL[nNumRules];     
  85.     m_bSubscribed = new BOOL[nNumRules];
  86.     m_bUnsubscribePending = new BOOL[nNumRules];
  87.     m_lastASMFlagsForThisRule = new UINT8[nNumRules];
  88.     m_OnDepends = new UINT16*[nNumRules];
  89.     m_OffDepends = new UINT16*[nNumRules];
  90.     for (UINT16 i = 0; i < nNumRules; i++)
  91.     {
  92. m_bNeedSwitchOff[i] = FALSE;
  93. m_bSubscribePending[i] = FALSE;
  94. m_bSubscribed[i] = FALSE;
  95. m_bUnsubscribePending[i] = FALSE;
  96. m_lastASMFlagsForThisRule[i] = 0;
  97. m_OnDepends[i] = NULL;
  98. m_OffDepends[i] = NULL;
  99.     }
  100.     ParseRuleBookForDirectives(m_nNumRules, pRuleBook, usBookSize,
  101. m_bNeedSwitchOff, m_OffDepends, m_OnDepends);
  102. }
  103. /****************************************************************************
  104.  *  Method:
  105.  *    CASMRuleState::~CASMRuleState
  106.  *
  107.  */
  108. CASMRuleState::~CASMRuleState()
  109. {
  110.     HX_VECTOR_DELETE(m_bSubscribePending);
  111.     HX_VECTOR_DELETE(m_bSubscribed);
  112.     HX_VECTOR_DELETE(m_bUnsubscribePending);
  113.     HX_VECTOR_DELETE(m_lastASMFlagsForThisRule);
  114.     HX_VECTOR_DELETE(m_bNeedSwitchOff);
  115.     for (UINT16 i = 0; i < m_nNumRules; i++)
  116.     {
  117. HX_VECTOR_DELETE(m_OffDepends[i]);
  118. HX_VECTOR_DELETE(m_OnDepends[i]);
  119.     }
  120.     HX_VECTOR_DELETE(m_OffDepends);
  121.     HX_VECTOR_DELETE(m_OnDepends);
  122.     m_nNumRules = 0;
  123. }
  124. /****************************************************************************
  125.  *  Method:
  126.  *    CASMRuleState::ParseRuleBookDirectives
  127.  *
  128.  */
  129. void 
  130. CASMRuleState::ParseRuleBookForDirectives(UINT16 num_rules,
  131.   char* pRuleBook,
  132.   UINT16 usBookSize,
  133.   BOOL* pNeedSwitchOff,
  134.   UINT16** pOffDepends, 
  135.   UINT16** pOnDepends)
  136. {
  137.     char* pOffset = pRuleBook;
  138.     UINT16 idxCurrentRule = 0;
  139.     while(*pOffset != '' && ((UINT16)(pOffset - pRuleBook) < usBookSize))
  140.     {
  141. while(*pOffset != ';')
  142. {
  143.     if (*pOffset == 'w' || *pOffset == 'W')
  144.     {
  145. // check to see if we have a wait directive
  146. if (strncasecmp(WAITFORSWITCHOFF, pOffset, 
  147. WAITFORSWITCHOFFLEN) == 0)
  148. {
  149.     pOffset += WAITFORSWITCHOFFLEN;
  150.     
  151.     SKIP_WHITE_SPACE(pOffset);
  152.     // should have an = sign
  153.     HX_ASSERT(*pOffset == '=');
  154.     pOffset ++;
  155.     SKIP_WHITE_SPACE(pOffset);
  156.     pNeedSwitchOff[idxCurrentRule] = 
  157. (*pOffset == 't' || *pOffset == 'T');
  158. }
  159.     }
  160.     if (*pOffset == 'o' || *pOffset == 'O')
  161.     {
  162. BOOL bDependsList = FALSE;
  163. UINT16* pDependsList = NULL;
  164. if (strncasecmp(ONDEPEND, pOffset, 
  165. ONDEPENDLEN) == 0)
  166. {
  167.     bDependsList = TRUE;
  168.     pDependsList = new UINT16[num_rules];
  169.     pOnDepends[idxCurrentRule] = pDependsList;
  170.     memset(pDependsList, 0xFF, sizeof(UINT16) * num_rules);
  171.     pOffset += ONDEPENDLEN;
  172. }
  173. else if (strncasecmp(OFFDEPEND, pOffset, 
  174. OFFDEPENDLEN) == 0)
  175. {
  176.     bDependsList = TRUE;
  177.     pDependsList = new UINT16[num_rules];
  178.     pOffDepends[idxCurrentRule] = pDependsList;
  179.     memset(pDependsList, 0xFF, sizeof(UINT16) * num_rules);
  180.     pOffset += OFFDEPENDLEN;
  181. }
  182. if (bDependsList)
  183. {
  184.     SKIP_WHITE_SPACE(pOffset);
  185.     HX_ASSERT(*pOffset == '=');
  186.     pOffset++;
  187.     SKIP_WHITE_SPACE(pOffset);
  188.     pOffset = ParseDependsList(pOffset, pDependsList);
  189. }
  190.     }
  191.     pOffset++;
  192. }
  193. idxCurrentRule++;
  194. pOffset++;
  195.     }
  196. }
  197. /****************************************************************************
  198.  *  Method:
  199.  *    CASMRuleState::ParseRuleBookDirectives
  200.  *
  201.  */
  202. char* 
  203. CASMRuleState::ParseDependsList(char* pDependsText, UINT16* pDependsList)
  204. {
  205.     char* pOffset = pDependsText;
  206.     UINT16 idxCurrentDepends = 0;
  207.     UINT16 nCurrentDepends = 0;
  208.     
  209.     SKIP_WHITE_SPACE(pOffset);
  210.     // depends directive list is in "'s
  211.     if (*pOffset != '"')
  212.     {
  213. HX_ASSERT(*pOffset == '"');
  214.     }
  215.     else
  216.     {
  217. // skip the first "
  218. pOffset++;
  219. // parse string till we find the last "
  220. while (*pOffset != '"')
  221. {
  222.             SKIP_WHITE_SPACE(pOffset);
  223.     // should be a list of numbers and we are at the beginning of one
  224.     while(*pOffset >= '0' && *pOffset <= '9')
  225.     {
  226. nCurrentDepends =  
  227.     (nCurrentDepends * 10) + *pOffset - '0';
  228. pOffset++;
  229.     }
  230.     pDependsList[idxCurrentDepends] = nCurrentDepends;
  231.     SKIP_WHITE_SPACE(pOffset);
  232.     // depend numbers are seperated by commas or this could be
  233.     // the last one
  234.     if (*pOffset == ',')
  235.     {
  236. pOffset++;
  237.     }
  238.     else
  239.     {
  240. // if it wasn't a comma, it better be the end of the depends
  241. // list
  242. HX_ASSERT(*pOffset == '"');
  243.     }
  244. }
  245.     }
  246.     return pOffset;
  247. }
  248. /****************************************************************************
  249.  *  Method:
  250.  *    CASMRuleState::StartSubscribePending
  251.  *
  252.  */
  253. void 
  254. CASMRuleState::StartSubscribePending(UINT16 usRuleNum)
  255. {
  256.     HX_ASSERT(usRuleNum < m_nNumRules);
  257. //printf("%luttSubscribe Pending:t%un", this, usRuleNum);
  258.     if (m_bUnsubscribePending[usRuleNum])
  259.     {
  260. //printf("%luttImediate Subscribe (was pending Unsubscribe):t%un", this, usRuleNum);
  261. m_bUnsubscribePending[usRuleNum] = FALSE;
  262. m_bSubscribed[usRuleNum] = TRUE;
  263.     }
  264.     else
  265.     {
  266.         m_bSubscribePending[usRuleNum] = TRUE;
  267.     }
  268. }
  269. /****************************************************************************
  270.  *  Method:
  271.  *    CASMRuleState::CanSubscribeNow
  272.  *
  273.  */
  274. BOOL
  275. CASMRuleState::CanSubscribeNow(UINT16 usRuleNum)
  276. {
  277.     // check for OnDepen dependent rules for this rule, if they are all
  278.     // subscribed then this rule can subscribe
  279.     UINT16 idxDepend;
  280.     BOOL bAllDependsSubscribed = TRUE;
  281.     if (m_OnDepends[usRuleNum] != NULL)
  282.     {
  283. // once we find one depend pending we can stop looking
  284. for (idxDepend = 0; idxDepend < m_nNumRules && 
  285. m_OnDepends[usRuleNum][idxDepend] != NO_DEPEND_SET && 
  286. bAllDependsSubscribed; idxDepend++)
  287. {
  288.     // if the dependent rule is not subscribed then we have a
  289.     // dependPending
  290.     bAllDependsSubscribed = 
  291. m_bSubscribed[m_OnDepends[usRuleNum][idxDepend]];
  292. }
  293.     }
  294.     // we can subscribe as long as all dependent rules are subscribed
  295.     return bAllDependsSubscribed;
  296. }
  297. /****************************************************************************
  298.  *  Method:
  299.  *    CASMRuleState::CompleteSubscribe
  300.  *
  301.  */
  302. void
  303. CASMRuleState::CompleteSubscribe(UINT16 usRuleNum)
  304. {
  305.     HX_ASSERT(usRuleNum < m_nNumRules);
  306. //printf("%luttSubscribe Complete:t%urn", this, usRuleNum);
  307.     m_bSubscribePending[usRuleNum] = FALSE;
  308.     m_bSubscribed[usRuleNum] = TRUE;
  309. }
  310. /****************************************************************************
  311.  *  Method:
  312.  *    CASMRuleState::StartUnsubscribePending
  313.  *
  314.  */
  315. void
  316. CASMRuleState::StartUnsubscribePending(UINT16 usRuleNum)
  317. {
  318.     HX_ASSERT(usRuleNum < m_nNumRules);
  319. //printf("%luttUnsubscribe Pending:t%urn", this, usRuleNum);
  320.     if (m_bSubscribed[usRuleNum])
  321.     {
  322. m_bUnsubscribePending[usRuleNum] = TRUE;
  323.     }
  324.     else
  325.     {
  326. /*
  327.  * when a client subscribes to a rule and then decides to subscribe to a
  328.  * mutually exclusive rule (e.g. 8 and then 6), the subscribe to the second
  329.  * rule calls ASMRuleState::CancelStreamSwitch which clears all pending
  330.  * subscribes (i.e. the one to 8) and then starts a subscribe pending to 6.
  331.  * Later the client comes along and decides to explicitly unsubscribe to 8
  332.  * which causes an assertion failure in the asm rule state.  
  333.  */
  334. // HX_ASSERT(m_bSubscribePending[usRuleNum]);
  335. /*
  336.  *  This should be fine since a new subscription state must have been established.
  337.  */
  338.  
  339. // we can cancel this pending subscribe if we are unsubscribing
  340. m_bSubscribePending[usRuleNum] = FALSE;
  341.     }
  342. }
  343. /****************************************************************************
  344.  *  Method:
  345.  *    CASMRuleState::CanUnsubscribeNow
  346.  *
  347.  */
  348. BOOL
  349. CASMRuleState::CanUnsubscribeNow(UINT16 usRuleNum)
  350. {
  351.     // check for OffDepen dependent rules for this rule, if any are 
  352.     // subscribed then this rule can't unsubscribe
  353.     UINT16 idxDepend;
  354.     BOOL bAllDependsUnsubscribed = TRUE;
  355.     if (m_OffDepends[usRuleNum] != NULL)
  356.     {
  357. // once we find one depend pending we can stop looking
  358. for (idxDepend = 0; idxDepend < m_nNumRules && 
  359.       m_OffDepends[usRuleNum][idxDepend] != NO_DEPEND_SET && 
  360.       bAllDependsUnsubscribed; idxDepend++)
  361. {
  362.     // if the dependent rule is still subscribed then we have a
  363.     // dependent rule that's not unsubscribed
  364.     bAllDependsUnsubscribed = 
  365. !m_bSubscribed[m_OffDepends[usRuleNum][idxDepend]];
  366. }
  367.     }
  368.     // we can unsubscribe if there aren't any dependent rules subscribed
  369.     return bAllDependsUnsubscribed;
  370. }
  371. /****************************************************************************
  372.  *  Method:
  373.  *    CASMRuleState::CompleteUnsubscribe
  374.  *
  375.  */
  376. void
  377. CASMRuleState::CompleteUnsubscribe(UINT16 usRuleNum)
  378. {
  379.     HX_ASSERT(usRuleNum < m_nNumRules);
  380. //printf("%luttUnsubscribe Complete:t%urn", this, usRuleNum);
  381.     m_bUnsubscribePending[usRuleNum] = FALSE;
  382.     m_bSubscribed[usRuleNum] = FALSE;
  383. }
  384. /****************************************************************************
  385.  *  Method:
  386.  *    CASMRuleState::CanSwitchStreamsNow
  387.  *
  388.  */
  389. BOOL
  390. CASMRuleState::CanSwitchStreamsNow()
  391. {
  392.     UINT16 i = 0;
  393.     // if there are no unsubscribes pending && there are no subscribed
  394.     // rules
  395.     while (i < m_nNumRules && !m_bUnsubscribePending[i] && 
  396. !m_bSubscribed[i])
  397.     {
  398. i++;
  399.     }
  400.     return (i == m_nNumRules);
  401. }
  402. /****************************************************************************
  403.  *  Method:
  404.  *    CASMRuleState::CompleteStreamSwitch
  405.  *
  406.  */
  407. void
  408. CASMRuleState::CompleteStreamSwitch()
  409. {
  410. //printf("%lutt--->Compete Stream Switchrn", this);
  411.     // mark all of the pending rules subscribed to
  412.     for (UINT16 usRuleNumber = 0; usRuleNumber < m_nNumRules;
  413. usRuleNumber++)
  414.     {
  415. if (IsSubscribePending(usRuleNumber))
  416. {
  417.     CompleteSubscribe(usRuleNumber);
  418. }
  419.     }
  420. //printf("%lutt<---Stream Switch Completedrn", this);
  421. }
  422. /****************************************************************************
  423.  *  Method:
  424.  *    CASMRuleState::CancelStreamSwitch
  425.  *
  426.  */
  427. void
  428. CASMRuleState::CancelStreamSwitch()
  429. {
  430. //printf("%luttCancel Stream Switchrn", this);
  431.     // mark all of the pending rules subscribed to
  432.     for (UINT16 usRuleNumber = 0; usRuleNumber < m_nNumRules;
  433. usRuleNumber++)
  434.     {
  435. m_bSubscribePending[usRuleNumber] = FALSE;
  436.     }
  437. }
  438. /****************************************************************************
  439.  *  Method:
  440.  *    CASMRuleState::CompleteAllUnsubscribes
  441.  *
  442.  */
  443. void
  444. CASMRuleState::CompleteAllUnsubscribes()
  445. {
  446. //printf("%lutt--->Compete Unsubscribe All Rulesrn", this);
  447.     for (UINT16 usRuleNumber = 0; usRuleNumber < m_nNumRules;
  448. usRuleNumber++)
  449.     {
  450. if (IsUnsubscribePending(usRuleNumber))
  451. {
  452.     CompleteUnsubscribe(usRuleNumber);
  453. }
  454.     }
  455. //printf("%lutt<---All Rules Unsubscribe Completern", this);
  456. }
  457. /****************************************************************************
  458.  *  Method:
  459.  *    CASMRuleState::AnyPendingUnsubscribes
  460.  *
  461.  */
  462. BOOL 
  463. CASMRuleState::AnyPendingUnsubscribes()
  464. {
  465.     UINT16 usRuleNumber;
  466.     for (usRuleNumber = 0; usRuleNumber < m_nNumRules;
  467. usRuleNumber++)
  468.     {
  469. if (IsUnsubscribePending(usRuleNumber))
  470. {
  471.     break;
  472. }
  473.     }
  474.     return usRuleNumber < m_nNumRules;
  475. }
  476. /****************************************************************************
  477.  *  Method:
  478.  *    CASMRuleState::GetNextPendingUnsubscribe
  479.  *
  480.  */
  481. UINT16 
  482. CASMRuleState::GetNextPendingUnsubscribe()
  483. {
  484.     UINT16 usRuleNumber;
  485.     for (usRuleNumber = 0; usRuleNumber < m_nNumRules;
  486. usRuleNumber++)
  487.     {
  488. if (IsUnsubscribePending(usRuleNumber))
  489. {
  490.     break;
  491. }
  492.     }
  493.     HX_ASSERT(usRuleNumber < m_nNumRules);
  494.     return usRuleNumber;
  495. }