Автор | Сообщение |
|
| постоянный участник
|
Пост N: 1717
Зарегистрирован: 09.10.06
|
|
Отправлено: 19.09.21 10:32. Заголовок: Класс THmgData
Пример под катом показывает возможные проблемы с реализацией класса Скрытый текст
#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 ///////////////////////////////////////////////////////////////////////////////
|
| |
|
Ответов - 14
[только новые]
|
|
|
| постоянный участник
|
Пост N: 3895
Зарегистрирован: 17.02.12
|
|
Отправлено: 19.09.21 11:57. Заголовок: Петр пишет возможные..
Петр пишет цитата: | возможные проблемы с реализацией класса |
| В TKeyData это сделано специально, ключи как написано. Надо ли это в THmgData, по мне так не помешает, но может и не прав. Пример Скрытый текст
#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"}
|
| |
|
|
| постоянный участник
|
Пост N: 1719
Зарегистрирован: 09.10.06
|
|
Отправлено: 19.09.21 12:27. Заголовок: SergKis пишет: Надо..
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 )
| |
|
|
| постоянный участник
|
Пост N: 3896
Зарегистрирован: 17.02.12
|
|
Отправлено: 19.09.21 12:48. Заголовок: Петр пишет Что именн..
Петр пишет Например сохранить с такими же ключами, т.е. работаем в больших ключах (доп. 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 в таком же виде (ключи) с новыми значениями т.е. ваш пример 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
| |
|
|
| постоянный участник
|
Пост N: 1720
Зарегистрирован: 09.10.06
|
|
Отправлено: 19.09.21 13:20. Заголовок: SergKis пишет: В мо..
SergKis пишет: цитата: | В моем примере имеем ключи, как написано, т.е. они не доступны ? h:Host, h:Port Но если есть oHmgData() в upper, то в связке можно сохранить ini в таком же виде (ключи) с новыми значениями |
| Port конечно, его нет в ini. Если хотите получить h:Host просто оформите вызов hb_readini как hb_readini("demo.ini", .f.)
| |
|
|
| постоянный участник
|
Пост N: 3897
Зарегистрирован: 17.02.12
|
|
Отправлено: 19.09.21 13:26. Заголовок: Петр пишет Port коне..
Петр пишет цитата: | Port конечно, его нет в ini. |
| Это да, но Host есть. Основная методика работать не :Set(), :Get(), а o:<char имя ключа>, hb_readini() просто для примера, показать ключи, как написано.
| |
|
|
| постоянный участник
|
Пост N: 1721
Зарегистрирован: 09.10.06
|
|
Отправлено: 19.09.21 13:54. Заголовок: Петр пишет: Это да,..
Петр пишет: Петр пишет: цитата: | Если хотите получить 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., почему я не могу получить ожидаемый результат?
| |
|
|
| постоянный участник
|
Пост N: 3899
Зарегистрирован: 17.02.12
|
|
Отправлено: 19.09.21 14:50. Заголовок: Петр пишет а вы може..
Петр пишет цитата: | а вы можете не отвечать на них или давать уклончивые ответы |
| Так я думал, что тут все ясно, очевидно 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} Извините. Я же не знаю для каких целей так делаете o:Set( hb_Hash( "_FormMain", 1, "_FormAbout", 200 ) ) может так и надо, как с hb_readini() я проделал
| |
|
|
| постоянный участник
|
Пост N: 3900
Зарегистрирован: 17.02.12
|
|
Отправлено: 20.09.21 08:38. Заголовок: Петр пишет я решил и..
Петр пишет цитата: | я решил использовать регистронезависимый поиск |
| Для oHmgData( .F. ) это подойдет лучше, чем строгое написание имен, т.е. правим CLASS THmgData ... METHOD New( lUpper ) INLINE ( ::lUpp := ! Empty( lUpper ), ; iif( ::lUpp, Nil, hb_hCaseMatch( ::aKey, .T. ) ), Self ) CONSTRUCTOR ...
| |
|
|
| постоянный участник
|
Пост N: 1722
Зарегистрирован: 09.10.06
|
|
Отправлено: 20.09.21 22:55. Заголовок: SergKis пишет: Я же..
SergKis пишет: цитата: | Я же не знаю для каких целей так делаете o:Set( hb_Hash( "_FormMain", 1, "_FormAbout", 200 ) ) |
| Просто тестировал класс Вот таким кодом (крайняя версия) Скрытый текст
#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
| Версия THmgData для выпуска 21.09.
| |
|
|
| постоянный участник
|
Пост N: 1723
Зарегистрирован: 09.10.06
|
|
Отправлено: 20.09.21 23:00. Заголовок: Вот результат 1. ===..
Вот результат 1. ======== 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 ======== 2. ======== 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 ======== Меня не порадовал. Результат после hb_hSetCaseMatch(h, .f.) 3. ======== 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 ======== 4. ======== 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 ======== Уже лучше
| |
|
|
| постоянный участник
|
Пост N: 1724
Зарегистрирован: 09.10.06
|
|
Отправлено: 20.09.21 23:03. Заголовок: SergKis пишет: прав..
SergKis пишет: цитата: | правим CLASS THmgData ... METHOD New( lUpper ) INLINE ( ::lUpp := ! Empty( lUpper ), ; iif( ::lUpp, Nil, hb_hCaseMatch( ::aKey, .T. ) ), Self ) CONSTRUCTOR ... |
| Мало что даст
| |
|
|
|
| постоянный участник
|
Пост N: 3901
Зарегистрирован: 17.02.12
|
|
Отправлено: 21.09.21 00:18. Заголовок: Петр пишет Версия TH..
Петр пишет цитата: | Версия 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 ) ) Просто тестировал класс |
| Самый первый пример отработал как надо и я не мог врубиться в суть вопроса
| |
|
|
| постоянный участник
|
Пост N: 1725
Зарегистрирован: 09.10.06
|
|
Отправлено: 21.09.21 02:13. Заголовок: SergKis пишет: :Set..
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.)
| |
|
|
| постоянный участник
|
Пост N: 3902
Зарегистрирован: 17.02.12
|
|
Отправлено: 21.09.21 11:17. Заголовок: Петр пишет METHOD Se..
Петр пишет цитата: | 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
| |
|
|
|