Форум » GUI » Класс THmgData » Ответить

Класс THmgData

Петр: Пример под катом показывает возможные проблемы с реализацией класса [more][pre2]#define _HMG_OUTLOG #ifdef _HMG_OUTLOG #include "hmg.ch" #endif Function Main() Local o := oHmgData(), h o:Set( hb_Hash( "_FormMain", 1, "_FormAbout", 200 ) ) o:Set( "_FormOther", 99 ) o:Set( "_FormPreff", 67 ) s_ObjTest( o ) h := o:CloneHash() o := Nil o := YATHmgData():New( .f. ) o:Set( h ) //hb_HClear( h ) s_ObjTest( o ) Return Static Function s_ObjTest( obj ) Local e ? '--------' ? obj:ClassName() ? '--------' ? "s:", PadR("_FormMain", 12), obj:Get( "_FormMain", 404 ) ? "s:", PadR("_FORMMAIN", 12), obj:Get( "_FORMMAIN", 404 ) ? "s:", PadR("_FORMOTHER", 12), obj:Get( "_FORMOTHER", 404 ) ? "s:", PadR("_formother", 12), obj:Get( "_formother", 404 ) for each e in obj:GetAll() ? "f:", PadR(e[1], 12), StrZero(e[2],3), e:__enumIndex() next for each e in obj:GetAll( .t. ) ? "t:", StrZero(e,3), e:__enumIndex() next Return #ifdef __XHARBOUR__ #include "hbcompat.ch" #endif #include "hbclass.ch" #define _METHOD METHOD /////////////////////////////////////////////////////////////////////////////// CLASS YATHmgData // Y[et]A[nother]HmgData /////////////////////////////////////////////////////////////////////////////// PROTECTED: VAR lMatch AS LOGICAL VAR aHash AS HASH INIT { => } EXPORTED: VAR Cargo METHOD New( lMatch ) INLINE ( ::lMatch := !Empty( lMatch ), hb_hCaseMatch( ::aHash, ::lMatch ), Self ) METHOD Set( Key, Val ) INLINE iif( HB_ISHASH( Key ), ::aHash := hb_hSetCaseMatch( Key, ::lMatch), hb_HSet( ::aHash, Key, Val ) ) METHOD Get( Key, DefVal ) INLINE hb_HGetDef( ::aHash, Key, DefVal ) METHOD Del( Key ) INLINE iif( ::Pos( Key ) > 0, hb_HDel( ::aHash, Key ), Nil ) METHOD Pos( Key ) INLINE hb_HPos( ::aHash, Key ) METHOD Len() INLINE Len( ::aHash ) METHOD Keys() INLINE hb_HKeys( ::aHash ) METHOD Values() INLINE hb_HValues( ::aHash ) METHOD CloneHash() INLINE hb_HClone( ::aHash ) _METHOD GetAll( lOnlyVal ) _METHOD Eval( xBlock ) ERROR HANDLER ControlAssign ENDCLASS /////////////////////////////////////////////////////////////////////////////// METHOD GetAll( lOnlyVal ) CLASS YATHmgData LOCAL aRet := {} IF HB_ISLOGICAL( lOnlyVal ) .AND. lOnlyVal //hb_HEval( ::aHash, {| k, v, i | AAdd( aRet, v ) } ) aRet := ::Values() ELSE hb_HEval( ::aHash, {| k, v, i | AAdd( aRet, { k, v } ) } ) ENDIF RETURN aRet METHOD Eval( xBlock ) CLASS YATHmgData LOCAL b := HB_ISBLOCK( xBlock ) LOCAL l := HB_ISLOGICAL( xBlock ) .AND. xBlock LOCAL aRet := iif( b, NIL, {} ) IF b hb_HEval( ::aHash, xBlock ) ELSEIF l //hb_HEval( ::aHash, {| k, v, i | AAdd( aRet, v ) } ) aRet := ::Values() ELSE hb_HEval( ::aHash, {| k, v, i | AAdd( aRet, { v, k, i } )} ) ENDIF RETURN aRet METHOD ControlAssign( xValue ) CLASS YATHmgData LOCAL cMessage, uRet LOCAL lError := iif( PCount() <= 1, .F., .T. ) cMessage := __GetMessage() IF PCount() == 1 ::Set( SubStr( cMessage, 2 ), xValue ) ENDIF uRet := iif( lError, ::Get( cMessage ), NIL ) uRet := iif( !lError, ::Get( cMessage ), NIL ) IF lError ::MsgNotFound( cMessage ) ENDIF RETURN uRet /////////////////////////////////////////////////////////////////////////////// [/pre2] [/more]

Ответов - 14

SergKis: Петр пишет возможные проблемы с реализацией класса В TKeyData это сделано специально, ключи как написано. Надо ли это в THmgData, по мне так не помешает, но может и не прав. Пример [pre2] #define _HMG_OUTLOG #include "hmg.ch" Function Main() Local o := oHmgData(), h, e, a o:Set(hb_readini("demo.ini")) for each e in o:GetAll() IF e[1] == [COM] h := oHmgData() h:Set(e[2]) for each a in h:GetAll() ? a:__enumIndex(), hb_valtoexp(a) next ENDIF next Return demo.ini [COM] DiskArc = D:\eAlarm\BACKUP ; Archives storage location (files *.7z) PathArc = .\BAKS ; Archived copies daemon_*.7z for timing PathXml = .\XML ; directory for excel reporting PathBAK = .\BAK ; Auto loading files *.fdb from files *.bak ModeBAK = 1 ; 1 - delete fdb after loading fdb, 0 - no delete LoadBAK = 1 ; loaded: 0 - last bak, 1 - all bak files from directoy ModeFDB = 1 ; 1 - delete all dbf after loading fdb, 0 - no delete User = sysdba ; FDB user Password = masterkey ; FDB password TimerSek = 30 ; usage: 60*60 = 1 hour or 60*60*3 = 3 hours TimeLoad = 17:15:00 ; , 23:00:00-23:59:59 ; time load *.7z => *.bak Host = 127.0.0.1 ; Language = RU результат 1 {"DiskArc", "D:\eAlarm\BACKUP ; Archives storage location (files *.7z)"} 2 {"PathArc", ".\BAKS ; Archived copies daemon_*.7z for timing"} 3 {"PathXml", ".\XML ; directory for excel reporting"} 4 {"PathBAK", ".\BAK ; Auto loading files *.fdb from files *.bak"} 5 {"ModeBAK", "1 ; 1 - delete fdb after loading fdb, 0 - no delete"} 6 {"LoadBAK", "1 ; loaded: 0 - last bak, 1 - all bak files from directoy"} 7 {"ModeFDB", "1 ; 1 - delete all dbf after loading fdb, 0 - no delete"} 8 {"User", "sysdba ; FDB user"} 9 {"Password", "masterkey ; FDB password"} 10 {"TimerSek", "30 ; usage: 60*60 = 1 hour or 60*60*3 = 3 hours"} 11 {"TimeLoad", "17:15:00 ; , 23:00:00-23:59:59 ; time load *.7z => *.bak"} 12 {"Host", "127.0.0.1 ;"} 13 {"Language", "RU"} [/pre2]

Петр: SergKis пишет: Надо ли это в THmgData, по мне так не помешает, но может и не прав Что именно не помешает? hb_readini("demo.ini") HB_FUNC_TRANSLATE( HB_READINI , HB_INIREAD ) FUNCTION hb_iniRead( cFileSpec, lKeyCaseSens, cSplitters, lAutoMain ) RETURN hb_iniReadStr( iif( HB_ISSTRING( cFileSpec ), hb_iniFileLow( cFileSpec ), "" ), lKeyCaseSens, cSplitters, lAutoMain ) FUNCTION hb_iniReadStr( cData, lKeyCaseSens, cSplitters, lAutoMain ) LOCAL hIni := { => } /* Default case sensitiveness for keys */ hb_default( @lKeyCaseSens, .T. ) hb_default( @lAutoMain, .T. ) hb_HCaseMatch( hIni, lKeyCaseSens )

SergKis: Петр пишет Что именно не помешает? Например сохранить с такими же ключами, т.е. работаем в больших ключах (доп. oHmgData()), а сохраняем по представленному выше в связке на дополнительный. Есть или нет такой вариант в THmgData большого значения не имеет, по мне. FUNCTION hb_iniReadStr( cData, lKeyCaseSens, cSplitters, lAutoMain ) LOCAL hIni := { => } /* Default case sensitiveness for keys */ hb_default( @lKeyCaseSens, .T. ) hb_default( @lAutoMain, .T. ) hb_HCaseMatch( hIni, lKeyCaseSens ) не очень понял что хотели сказать. В моем примере имеем ключи, как написано, т.е. они не доступны ? h:Host, h:Port Но если есть oHmgData() в upper, то в связке можно сохранить ini в таком же виде (ключи) с новыми значениями т.е. ваш пример[pre2] o := YATHmgData():New( .f. ) o:Set( h ) ? "YATHmgData() ***",o:_FormMain s_ObjTest( o ) даст YATHmgData() *** NIL вариант o := YATHmgData():New( .t. ) o:Set( h ) ? "YATHmgData() ***",o:_FormMain s_ObjTest( o ) даст YATHmgData() *** NIL [/pre2]


Петр: SergKis пишет: В моем примере имеем ключи, как написано, т.е. они не доступны ? h:Host, h:Port Но если есть oHmgData() в upper, то в связке можно сохранить ini в таком же виде (ключи) с новыми значениями Port конечно, его нет в ini. Если хотите получить h:Host просто оформите вызов hb_readini как hb_readini("demo.ini", .f.)

SergKis: Петр пишет Port конечно, его нет в ini. Это да, но Host есть. Основная методика работать не :Set(), :Get(), а o:<char имя ключа>, hb_readini() просто для примера, показать ключи, как написано.

Петр: Петр пишет: Это да, но Host есть. Петр пишет: Если хотите получить h:Host просто оформите вызов hb_readini как hb_readini("demo.ini", .f.) ? h:Host, h:Port 127.0.0.1 ; NIL SergKis пишет: Основная методика работать не :Set(), :Get(), а o:<char имя ключа> Это ваша методика и вам ее никто не запрещает использовать. Но я ее не обязан использовать, как и не обязан запоминать в каком регистре у меня описаны секции в ini файле. Вы можете писать классы, методы которых дублируют друг друга, вы можете писать код заточенный под ваши нужды. Но, поскольку все это находится в общедоступной открытой библиотеке, я могу задавать вопросы, а вы можете не отвечать на них или давать уклончивые ответы Вы можете объяснить поведение класса THmgData в моем примере, я решил использовать регистронезависимый поиск - установил lUpp в .T., почему я не могу получить ожидаемый результат?

SergKis: Петр пишет а вы можете не отвечать на них или давать уклончивые ответы Так я думал, что тут все ясно, очевидно [pre2] Function Main() Local o := oHmgData(), h, e, a h := oHmgData() h:Set( "_FormMain" , 101 ) h:Set( "_FormAbout", 202 ) o:Set( h:CloneHash() ) ? o:GetAll() ; ?v o:GetAll() ; ? o := oHmgData() o:Set( hb_Hash( "_FormMain", 1, "_FormAbout", 200 ) ) ? o:GetAll() ; ?v o:GetAll() ; ? Return ARRAY[2] 1 {"_FORMMAIN", 101} 2 {"_FORMABOUT", 202} ARRAY[2] 1 {"_FormMain", 1} 2 {"_FormAbout", 200} [/pre2] Извините. Я же не знаю для каких целей так делаете o:Set( hb_Hash( "_FormMain", 1, "_FormAbout", 200 ) ) может так и надо, как с hb_readini() я проделал

SergKis: Петр пишет я решил использовать регистронезависимый поиск Для oHmgData( .F. ) это подойдет лучше, чем строгое написание имен, т.е. правим [pre2] CLASS THmgData ... METHOD New( lUpper ) INLINE ( ::lUpp := ! Empty( lUpper ), ; iif( ::lUpp, Nil, hb_hCaseMatch( ::aKey, .T. ) ), Self ) CONSTRUCTOR ... [/pre2]

Петр: SergKis пишет: Я же не знаю для каких целей так делаете o:Set( hb_Hash( "_FormMain", 1, "_FormAbout", 200 ) ) Просто тестировал класс Вот таким кодом (крайняя версия) [pre2]#define _HMG_OUTLOG #ifdef _HMG_OUTLOG #include "hmg.ch" #endif Function Main() Local o := oHmgData() Local h := hb_Hash("_FormMain", 1, "_FormAbout", 200) //o:Set(hb_hSetCaseMatch(h, .f.)) o:Set(h) o:Set("_FormOther", 99) o:Set("_FormPreff", 67) s_ObjTest( 'oHmgData()', o) ? '--------' ? o:ClassName(), '***', o:_FormMain, "|", o:_FORMMAIN, "|", o:_FORMOTHER ? '========' Return Static Function s_ObjTest( p, obj ) Local e ? '========' ? obj:ClassName() ? '--------' p += ':' ? p, PadR("_FORMMAIN", 16), obj:Get( "_FORMMAIN", 404 ) ? p, PadR("_formmain", 16), obj:Get( "_formmain", 404 ) ? p, PadR("_FormMain", 16), obj:Get( "_FormMain", 404 ) ? p, PadR("_FORMOTHER", 16), obj:Get( "_FORMOTHER", 404 ) ? p, PadR("_formother", 16), obj:Get( "_formother", 404 ) ? p, PadR("_FormOther", 16), obj:Get( "_FormOther", 404 ) for each e in obj:GetAll() ? e:__enumIndex(), PadR(e[1], 16), e[2] next Return [/pre2] Версия THmgData для выпуска 21.09.

Петр: Вот результат 1. [pre2]======== THMGDATA -------- oHmgData(.t.): _FORMMAIN 404 oHmgData(.t.): _formmain 404 oHmgData(.t.): _FormMain 404 oHmgData(.t.): _FORMOTHER 99 oHmgData(.t.): _formother 99 oHmgData(.t.): _FormOther 99 1 _FormMain 1 2 _FormAbout 200 3 _FORMOTHER 99 4 _FORMPREFF 67 -------- THMGDATA *** NIL | NIL | 99 ======== [/pre2] 2. [pre2]======== THMGDATA -------- oHmgData(.f.): _FORMMAIN 404 oHmgData(.f.): _formmain 404 oHmgData(.f.): _FormMain 1 oHmgData(.f.): _FORMOTHER 404 oHmgData(.f.): _formother 404 oHmgData(.f.): _FormOther 99 1 _FormMain 1 2 _FormAbout 200 3 _FormOther 99 4 _FormPreff 67 -------- THMGDATA *** NIL | NIL | NIL ======== [/pre2] Меня не порадовал. Результат после hb_hSetCaseMatch(h, .f.) 3. [pre2]======== THMGDATA -------- oHmgData(.t.): _FORMMAIN 1 oHmgData(.t.): _formmain 1 oHmgData(.t.): _FormMain 1 oHmgData(.t.): _FORMOTHER 99 oHmgData(.t.): _formother 99 oHmgData(.t.): _FormOther 99 1 _FormMain 1 2 _FormAbout 200 3 _FORMOTHER 99 4 _FORMPREFF 67 -------- THMGDATA *** 1 | 1 | 99 ======== [/pre2] 4. [pre2]======== THMGDATA -------- oHmgData(.f.): _FORMMAIN 1 oHmgData(.f.): _formmain 1 oHmgData(.f.): _FormMain 1 oHmgData(.f.): _FORMOTHER 99 oHmgData(.f.): _formother 99 oHmgData(.f.): _FormOther 99 1 _FormMain 1 2 _FormAbout 200 3 _FormOther 99 4 _FormPreff 67 -------- THMGDATA *** 1 | 1 | 99 ========[/pre2] Уже лучше

Петр: SergKis пишет: правим CLASS THmgData ... METHOD New( lUpper ) INLINE ( ::lUpp := ! Empty( lUpper ), ; iif( ::lUpp, Nil, hb_hCaseMatch( ::aKey, .T. ) ), Self ) CONSTRUCTOR ... Мало что даст

SergKis: Петр пишет Версия THmgData для выпуска 21.09. Наверно надо сказать, что закладывал. 1. oHmgData(.F.) - работа по строгим именам переменных, т.е. как написано 2. oHmgData(.T.) - аналог public\private переменных имена\ключи в больших буквах сразу Метод Set, сначала, ловил Hash и Array и проделывал все с учетом :lUpp, потом это убрал, так как можно все проделать внешними AEval или FOR. Основная работа :Set(), :Get(), :Del(), :CloneHash(), :GetAll(), + o:<имя_переменной> :Set( hb_Hash(...) ) надо давать с использованием hb_hCaseMatch(), при .f. строгие имена, ::lUpp := .F. Для oHmgData(.T.) o:Set( hb_Hash( "_FormMain", 1, "_FormAbout", 200 ) ) и мой hb_readini() нормальная ситуация создания защищенных данных, т.е. не доступны :Set(), :Get(), :Del(), но доступны :GetAll(), :CloheHash(). Из защищенных данных можно создать другой :lUpp := .T. или писать в o h := oHmgData(.t.) for ech a in o:GetAll() ; h:Set(a[1], a[2]) next потом менять в h и в конце связать o и h по ключам, что то проделав с данными из o и h, ключ из o Мне, например, такие варианты были нужны. PS Основное это :CloneHash(), а :Set( hb_Hash(...) ) это побочка, т.е. (вся ответственность на человеке) h := o:CloneHash() меняем в o значения, что то делаем на их основе возвращаем o:Set( h ) Мало что даст Согласен, но подумал, что может никому, кроме меня, не нужна работа по строгим именам o:Set( hb_Hash( "_FormMain", 1, "_FormAbout", 200 ) ) Просто тестировал класс Самый первый пример отработал как надо и я не мог врубиться в суть вопроса

Петр: SergKis пишет: :Set( hb_Hash(...) ) надо давать с использованием hb_hCaseMatch() Можно изменить METHOD Set( Key, xVal ) INLINE ; iif( HB_ISHASH( Key ), ::aKey := hb_hSetCaseMatch( Key, iif( HB_ISLOGICAL( xVal ), xVal, !::lUpp ) ), hb_HSet( ::aKey, ::Upp( Key ), xVal ) ) тогда вместо o:Set(hb_hSetCaseMatch(h, .f.)) пишем o:Set(h, .f.)

SergKis: Петр пишет METHOD Set( Key, xVal ) INLINE ; iif( HB_ISHASH( Key ), ::aKey := hb_hSetCaseMatch( Key, iif( HB_ISLOGICAL( xVal ), xVal, !::lUpp ) ), hb_HSet( ::aKey, ::Upp( Key ), xVal ) ) Не уверен, что это надо, т.к. для внешнего Hash можно использовать весь набор ф-й для работы с Hash. o:Set( hb_HSort( o:CloneHash() ) ) o:Set( hb_HFill( o:CloneHash(), "" ) ) или пополнять методами THmgData, так только недавно их убирал, в TKeyData они есть PS Всегда можно сделать свой класс с расширенными возможностями CLASS TVarData INHERIT THmgData



полная версия страницы