source: anotherchoice/tags/jsp-1.4.4-full-UTF8/cfg/base/directorymap.cpp@ 26

Last change on this file since 26 was 26, checked in by ykominami, 10 years ago

initial

File size: 22.3 KB
Line 
1/*
2 * TOPPERS/JSP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Just Standard Profile Kernel
5 *
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 *
9 * 上記著作権者
10は,以下の (1)〜(4) の条件か,Free Software Foundation
11 * によってå…
12¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
13 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
14 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
15å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
16 * 利用と呼ぶ)することを無償で許諾する.
17 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
18 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
19 * スコード中に含まれていること.
20 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
21 * 用できる形で再é…
22å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
23å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
24 * 者
25マニュアルなど)に,上記の著作権表示,この利用条件および下記
26 * の無保証規定を掲載すること.
27 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
28 * 用できない形で再é…
29å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
30 * と.
31 * (a) 再é…
32å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
33マニュアルなど)に,上記の著
34 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
35 * (b) 再é…
36å¸ƒã®å½¢æ…
37‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
38 * 報告すること.
39 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
40 * 害からも,上記著作権者
41およびTOPPERSプロジェクトをå…
42è²¬ã™ã‚‹ã“と.
43 *
44 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
45お
46 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
47 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
48 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
49 *
50 * @(#) $Id: directorymap.cpp,v 1.12 2003/12/15 07:32:13 takayuki Exp $
51 */
52
53
54// $Header: /home/CVS/configurator/base/directorymap.cpp,v 1.12 2003/12/15 07:32:13 takayuki Exp $
55
56/* MEMO:メモ書き
57 Q: こういうクラスはテンプレートにしたほうがいいと思うが?
58 A: ファイルに吐き出した後、読み出したときにどうやってクラス生成すべきかがわからない
59 (クラスファクトリを作るのはやめたい)
60 今と違う型を代å…
61¥ã•ã‚ŒãŸã¨ãã®å¯¾å‡¦æ³•ãŒã‚ã‹ã‚‰ãªã„
62*/
63
64
65#include "base/directorymap.h"
66#include "base/message.h"
67#include <stdarg.h>
68#include <typeinfo>
69#include <cassert>
70#include <cstdio>
71
72#ifdef _MSC_VER
73 #pragma warning(disable:4786)
74#endif
75
76using namespace std;
77
78int Directory::defaultflag = Directory::NOTHING;
79
80Directory::Directory(const Directory & src)
81{
82 parent = 0;
83 flag = defaultflag;
84 defaultflag &= ~DESTRUCT;
85
86 type = src.type;
87 switch(type)
88 {
89 case LITERAL:
90 content.literal = new string(*src.content.literal);
91 break;
92 default:
93 content = src.content;
94 break;
95 }
96}
97
98Directory::~Directory(void)
99{
100 disconnect(); //親との連結を解除
101 map<string,Directory*>::clear(); //子ノードの削除
102 clearContent(); //自分の中身を削除する
103}
104
105void Directory::clearContent(void)
106{
107 switch(this->getType())
108 {
109 case LITERAL:
110 delete content.literal;
111 break;
112 case OBJECT:
113 delete content.instance;
114 break;
115 default:
116 break;
117 }
118
119 type = UNKNOWN;
120 content.pointer = 0;
121}
122
123Directory * Directory::findNode(bool automatic_creation, const string & path)
124{
125 string::size_type top, tail, length;
126 string work;
127 Directory::iterator scope;
128 Directory * node = this;
129
130 if(this == NULL)
131 return NULL;
132
133 if(path.empty())
134 return this;
135
136 length = path.length();
137 top = 0;
138 if(path[0] == '/')
139 {
140 while(node->getParent() != 0)
141 node = node->getParent();
142 if(path.size() == 1)
143 return node;
144 top = 1;
145 }
146
147 do {
148 tail = path.find_first_of('/', top);
149 if(tail == string::npos)
150 work = path.substr(top);
151 else
152 work = path.substr(top, tail-top);
153
154 if(work.compare(".") == 0 || work.compare("..") == 0)
155 {
156 if(work.size() > 1 && node->getParent() != 0)
157 node = node->getParent();
158 }else
159 {
160 scope = node->begin();
161 while(scope != node->end())
162 {
163 if(work.compare((*scope).first) == 0)
164 break;
165 ++ scope;
166 }
167
168 if(scope == node->end())
169 {
170 if(!automatic_creation)
171 return 0;
172 node = node->addChild(work, new Directory);
173 }else
174 node = (*scope).second;
175 }
176 top = tail + 1;
177 } while( tail != string::npos && top < length );
178
179 return node;
180}
181
182Directory * Directory::findNode(bool automatic_creation, const char * key, va_list vl)
183{
184 Directory::iterator scope;
185 Directory * node = this;
186
187 if(this == NULL)
188 return NULL;
189
190 if(key == NULL)
191 return this;
192
193 if(*key == '/' && *(key+1) == '\x0')
194 {
195 while(node->getParent() != 0)
196 node = node->getParent();
197 if(vl == 0)
198 return node;
199 key = va_arg(vl, const char *);
200 }
201
202 do {
203 if(strcmp(key,".") != 0)
204 {
205 if(strcmp(key,"..") == 0)
206 {
207 node = node->parent;
208 }else
209 {
210 scope = node->begin();
211 while(scope != node->end())
212 {
213 if((*scope).first.compare(key) == 0)
214 break;
215 ++ scope;
216 }
217
218 if(scope == node->end())
219 {
220 if(!automatic_creation)
221 return 0;
222 node = node->addChild(key, new Directory);
223 }else
224 node = (*scope).second;
225 }
226 }
227 if(vl != 0)
228 key = va_arg(vl, const char *);
229 else
230 break;
231 } while( key != 0 && node != 0);
232
233 return node;
234}
235
236Directory & Directory::operator =(void * pointer)
237{
238 if(this->getType() != UNKNOWN && this->getType() != POINTER)
239 clearContent();
240
241 type = POINTER;
242 content.pointer = pointer;
243 return *this;
244}
245
246Directory & Directory::operator =(long value)
247{
248 if(this->getType() != UNKNOWN && this->getType() != INTEGER)
249 clearContent();
250
251 type = INTEGER;
252 content.value = value;
253 return *this;
254}
255
256Directory & Directory::operator =(const string & literal)
257{
258 if(this->getType() != UNKNOWN && this->getType() != LITERAL)
259 clearContent();
260
261 type = LITERAL;
262 content.literal = new string(literal);
263
264 return *this;
265}
266
267Directory & Directory::operator =(const char * constliteral)
268{
269 if(this->getType() != UNKNOWN && this->getType() != CONSTLITERAL)
270 clearContent();
271
272 type = CONSTLITERAL;
273 content.const_literal = constliteral;
274 return *this;
275}
276
277Directory & Directory::operator =(Garbage * instance)
278{
279 if(this->getType() != UNKNOWN)
280 clearContent();
281
282 type = OBJECT;
283 content.instance = instance;
284 return *this;
285}
286
287void * Directory::operator new(size_t sz)
288{
289 defaultflag |= DESTRUCT;
290 return ::operator new(sz);
291}
292
293void * Directory::operator new(size_t sz, nothrow_t)
294{
295 defaultflag |= DESTRUCT;
296 return ::operator new(sz, nothrow);
297}
298
299Directory::operator const long(void) const
300{
301 if( type == UNKNOWN )
302 ExceptionMessage("Bad cast exception","不正キャスト例外") << throwException;
303 return content.value;
304}
305
306void * Directory::operator * (void) const
307{
308 if( type == UNKNOWN )
309 ExceptionMessage("Bad cast exception","不正キャスト例外") << throwException;
310 return content.pointer;
311}
312
313Directory * Directory::addChild(const std::string & key, Directory * node)
314{
315 iterator scope;
316 std::pair<iterator, bool> work;
317
318 if(node == 0)
319 node = new Directory;
320 else
321 if(node->parent != 0)
322 node->disconnect();
323
324 node->parent = this;
325 if((scope = find(key)) != end())
326 {
327 Directory * old = (*scope).second;
328 old->disconnect();
329 old->erase();
330 }
331
332 work = insert(value_type(key, node));
333 node->myself = work.first;
334
335 return node;
336}
337
338Directory::iterator Directory::erase(iterator it)
339{
340 iterator result;
341 Directory * scope = (*it).second;
342
343 //戻り値の作成
344 if((result = it) == begin())
345 ++ result;
346 else
347 -- result;
348
349 //外したノードの後始末
350 if((scope->flag & DESTRUCT) != 0)
351 delete scope;
352 else
353 scope->erase();
354
355 return result;
356}
357
358void Directory::erase(void)
359{
360 iterator scope;
361
362 if(this != NULL)
363 {
364 if(parent != 0)
365 {
366 parent->erase(myself);
367 }else
368 {
369 while(!empty())
370 {
371 scope = begin();
372 if((scope->second->flag & DESTRUCT) != 0)
373 delete scope->second;
374 else
375 scope->second->erase();
376 }
377 }
378 }
379}
380
381void Directory::disconnect(void)
382{
383 if(parent != 0)
384 {
385 parent->map<string,Directory*>::erase(myself);
386 parent = 0;
387 }
388}
389
390Directory * Directory::getNext(void) const
391{
392 if(parent == 0)
393 return 0;
394
395 iterator scope;
396 scope = myself;
397 ++ scope;
398 if(scope == parent->end())
399 return 0;
400
401 return (*scope).second;
402}
403
404Directory * Directory::getPrev(void) const
405{
406 if(parent == 0 && myself == parent->begin())
407 return 0;
408
409 reverse_iterator scope;
410
411 scope = parent->rbegin();
412 while(scope != parent->rend() && (*scope).second != (*myself).second)
413 ++ scope;
414
415 ++ scope;
416 return scope != parent->rend() ? (*scope).second : 0;
417}
418
419bool Directory::changeKey(const string & key)
420{
421 Directory * scope;
422
423 if( key.size() == 0)
424 return false;
425
426 scope = parent;
427
428 disconnect();
429 scope->addChild(key, this);
430 return true;
431}
432
433
434void Directory::drawTree(ostream * out, int level, string * link)
435{
436 iterator scope;
437 iterator scope2;
438
439 if(level == 0)
440 link = new string;
441 else
442 *out << (*link).substr(0, (level-1)*3) << " +-";
443
444 *out << '[' << getKey() << ']';
445 switch(type)
446 {
447 case POINTER:
448 out->setf(ios::hex);
449 *out << " : PTR [" << content.pointer << "]";
450 break;
451 case INTEGER:
452 out->setf(ios::dec);
453 *out << " : INT [" << content.value << "]";
454 break;
455 case LITERAL:
456 *out << " : STR [" << *content.literal << "]";
457 break;
458 case CONSTLITERAL:
459 *out << " : CSTR[" << content.const_literal << "]";
460 break;
461 case OBJECT:
462 {
463 *out << " : OBJ";
464 break;
465 }
466 case UNKNOWN:
467 break;
468 default:
469 *out << "UNKNOWN";
470 }
471 *out << '\n';
472 (*link) += " | ";
473 scope = begin();
474 while(scope != end())
475 {
476 scope2 = scope;
477 ++ scope;
478
479 if(scope == end())
480 (*link)[level*3+1] = ' ';
481 (*scope2).second->drawTree(out, level+1, link);
482 }
483
484
485 link->erase(level*3);
486 if(level == 0)
487 delete link;
488}
489
490static string escapeXMLLiterals(const string & src)
491{
492 int index;
493 string::size_type pos;
494 string result;
495 const char literal[4] ="&<>";
496 const char * escape[3] = {"&amp;","&lt;","&gt;"};
497
498 result = src;
499 for(index = 0; index < 3; index++)
500 {
501 pos = 0;
502 while((pos = result.find_first_of(literal[index],pos)) != string::npos)
503 {
504 result.erase(pos,1);
505 result.insert(pos, escape[index]);
506 ++ pos;
507 }
508 }
509
510 return result;
511}
512
513static string encloseAttributes(const string & src)
514{
515 if(src.find_first_of('"') != string::npos)
516 return string("'") + src + "'";
517 return string("\"") + src + "\"";
518}
519
520void Directory::drawTree_byXML(ostream * out, int level)
521{
522 iterator scope;
523
524 if(level == 0)
525 *out << "<?xml version='1.0' encoding='Shift_JIS' ?>\n<?xml-stylesheet type='text/xsl' href='basic.xsl' ?>\n";
526
527 *out << "<node key=" << encloseAttributes(escapeXMLLiterals(getKey())) << " type='";
528
529 switch(type)
530 {
531 case POINTER:
532 out->setf(ios::hex);
533 *out << "PTR'><value>" << content.pointer << "</value>";
534 break;
535 case INTEGER:
536 out->setf(ios::dec);
537 *out << "INT'><value>" << content.value << "</value>";
538 break;
539 case LITERAL:
540 *out << "STR'><value>" << escapeXMLLiterals(*content.literal) << "</value>";
541 break;
542 case CONSTLITERAL:
543 *out << "CSTR'><value>" << escapeXMLLiterals(content.const_literal) << "</value>";
544 break;
545 case OBJECT:
546 *out << "OBJ'>";
547 break;
548 case UNKNOWN:
549 *out << "'>";
550 break;
551 default:
552 *out << "UNKNOWN'>";
553 }
554 *out << '\n';
555
556 scope = begin();
557 if(scope != end())
558 {
559 *out << "<child>\n";
560 do{
561 scope->second->drawTree_byXML(out, level+1);
562 ++ scope;
563 }while(scope != end());
564 *out << "</child>\n";
565 }
566 *out << "</node>\n";
567}
568
569Directory * Directory::findChild(const char * key)
570{
571 string work(key);
572 if(work.find_first_of('/') != string::npos)
573 return findChild(work);
574 return findNode(false, key, 0);
575}
576
577Directory * Directory::findChild(const char * key, const char * second, ... )
578{
579 va_list vl;
580 va_start(vl, second);
581 return findNode(false, key, 0)->findNode(false,second, vl);
582}
583
584Directory * Directory::openChild(const char * key)
585{
586 string work(key);
587 if(work.find_first_of('/') != string::npos)
588 return openChild(work);
589 return findNode(true, key, 0);
590}
591
592
593Directory * Directory::openChild(const char * key, const char * second, ... )
594{
595 va_list vl;
596 va_start(vl, second);
597 return findNode(true, key, 0)->findNode(true, second, vl);
598}
599
600 //指定したキーを持つ子孫を探す。サーチ順は中順
601Directory * Directory::findDescandant(const string & key, unsigned int level) const
602{
603 Directory::const_iterator scope;
604 const Directory * node = this;
605
606 if(empty())
607 return 0;
608
609 //子で探す
610 scope = begin();
611 while( scope != end() )
612 {
613 if((*scope).first.compare(key) == 0)
614 return const_cast<Directory *>((*scope).second);
615 ++ scope;
616 }
617
618 if(level > 0)
619 {
620 scope = begin();
621 while( scope != end() )
622 {
623 if((node = (*scope).second->findDescandant(key, level-1)) != 0)
624 return const_cast<Directory *>(node);
625 ++ scope;
626 }
627 }
628 return 0;
629}
630
631void Directory::copyTo(Directory * dest, int nest)
632{
633 Directory::iterator scope;
634 Directory * node;
635
636 if(this == NULL)
637 return;
638
639 assert(dest != NULL);
640
641 node = dest;
642 while(node != 0)
643 {
644 if(node == this)
645 ExceptionMessage("CopyTo: dest must not be a descendant node.","CopyTo: 子孫ノードへのコピーはできません") << throwException;
646 node = node->getParent();
647 }
648
649 scope = begin();
650 while(scope != end())
651 {
652 node = dest->findChild((*scope).first);
653 if(node != 0)
654 node->erase();
655
656 node = dest->addChild((*scope).first, new Directory(*(*scope).second));
657 if(nest > 0)
658 (*scope).second->copyTo(node, nest-1);
659
660 ++ scope;
661 }
662}
663
664void Directory::Store(ostream * out)
665{
666 int i;
667 Directory * node;
668
669 out->write((const char *)&type, sizeof(type));
670 switch(type)
671 {
672 case INTEGER:
673 out->write((const char *)&content.value, sizeof(content.value));
674 break;
675 case LITERAL:
676 i = content.literal->size();
677 out->write((const char *)&i, sizeof(int));
678 out->write(content.literal->c_str(), i);
679 break;
680 case CONSTLITERAL:
681 i = strlen(content.const_literal);
682 out->write((const char *)&i, sizeof(int));
683 out->write(content.const_literal, i);
684 break;
685 default:
686 out->write((const char *)&content.pointer, sizeof(content.pointer));
687 }
688 i = size();
689 out->write((const char *)&i, sizeof(int));
690 for(node = getFirstChild(); node != 0; node = node->getNext())
691 {
692 const string & work = node->getKey();
693 i = work.size();
694 out->write((const char *)&i, sizeof(int));
695 out->write(work.c_str(), i);
696 node->Store(out);
697 }
698}
699
700void Directory::Load(istream * in)
701{
702 int i;
703 int count;
704 char buffer[1024];
705
706 in->read((char *)&type, sizeof(type));
707 switch(type)
708 {
709 case INTEGER:
710 in->read((char *)&content.value, sizeof(content.value));
711 break;
712 case CONSTLITERAL:
713 case LITERAL:
714 in->read((char *)&i, sizeof(int));
715 in->read(buffer, i);
716 buffer[i] = '\x0';
717 *this = string(buffer);
718 break;
719 default:
720 in->read((char *)&content.pointer, sizeof(content.pointer));
721 }
722 in->read((char *)&count, sizeof(int));
723 while(count-- > 0)
724 {
725 in->read((char *)&i, sizeof(int));
726 in->read(buffer, i);
727 buffer[i] = '\x0';
728
729 addChild(buffer)->Load(in);
730 }
731}
732
733string Directory::toString(const string & default_value) const
734{
735 if(this == 0)
736 return default_value;
737
738 switch(type)
739 {
740 case POINTER:
741 case OBJECT:
742 {
743 char buffer[256];
744 sprintf(buffer,"%08lx", (long)content.pointer);
745 return string(buffer);
746 }
747 case INTEGER:
748 {
749 char buffer[256];
750 sprintf(buffer,"%ld", content.value);
751 return string(buffer);
752 }
753 case CONSTLITERAL:
754 return string(content.const_literal);
755 case LITERAL:
756 return string(*content.literal);
757 default:
758 return default_value;
759 }
760
761 return default_value;
762}
763
764void * Directory::toPointer(const void * default_value) const
765{
766 if(this == 0)
767 return (void *)default_value;
768
769 switch(type)
770 {
771 case INTEGER:
772 return (void *)&content.value;
773 case CONSTLITERAL:
774 return (void *)content.const_literal;
775 case LITERAL:
776 return (void *)content.literal->c_str();
777 case POINTER:
778 return (void *)content.pointer;
779 case OBJECT:
780 return (void *)content.instance;
781 default:
782 return (void *)default_value;
783 }
784
785 return (void *)default_value;
786}
787
788long Directory::toInteger(const long default_value) const
789{
790 bool minus = false;
791 long work;
792 const char * str;
793
794 if(this == 0)
795 return default_value;
796
797 switch(type)
798 {
799 case INTEGER:
800 return content.value;
801
802 case POINTER:
803 return (long)content.pointer;
804
805 case LITERAL:
806 case CONSTLITERAL:
807 if(type == CONSTLITERAL)
808 str = content.const_literal;
809 else
810 str = content.literal->c_str();
811
812 if(*str == '-')
813 {
814 minus = true;
815 str ++;
816 }
817
818 if(*str == '0')
819 {
820 str ++;
821 if(*str == 'x' || *str == 'X')
822 {
823 if(sscanf(str+1, "%ux", (int *)&work) == 0)
824 return default_value;
825 }else
826 if(*str != '\x0')
827 {
828 if(sscanf(str, "%o", (int *)&work) == 0)
829 return default_value;
830 }else
831 return 0;
832 }else
833 if(sscanf(str, "%d", (int *)&work) == 0)
834 return default_value;
835
836 if(minus)
837 work = -work;
838 return work;
839 default:
840 return default_value;
841 }
842
843 return default_value;
844}
845
846static string::size_type find_corresponding_parenthesis(const string & target, string::size_type pos = 0, char left = '(', char right = ')')
847{
848 int nest;
849
850 nest = 1;
851 do {
852 if(target[pos] == left)
853 {
854 ++ nest;
855 }else
856 {
857 if(target[pos] == right)
858 {
859 -- nest;
860 if(nest == 0)
861 return static_cast<int>(pos);
862 }
863 }
864 ++ pos;
865 }while(pos < target.size());
866
867 return string::npos;
868}
869
870
871string Directory::format(const string & fmt, int mode)
872{
873 Directory * node;
874 string work;
875 string key;
876 string default_value;
877 string::size_type top,tail;
878 string::size_type pos;
879 int i;
880
881 default_value.assign("(null)");
882 tail = 0;
883 while((top = fmt.find_first_of('$', tail)) != string::npos)
884 {
885 if(top != tail)
886 work += fmt.substr(tail, top - tail);
887
888 switch(fmt[top+1])
889 {
890 case '$':
891 tail = top+2;
892 work += '$';
893 break;
894
895 case '@':
896 work += (*myself).first;
897 tail = top + 2;
898 break;
899
900 case '(':
901 top += 2;
902 i = find_corresponding_parenthesis(fmt, top);
903 key = fmt.substr(top, i - top);
904
905 if(key.find_first_of('$') != string::npos)
906 key = format(key,mode);
907
908 pos = key.find_first_of(',');
909 if(pos != string::npos)
910 {
911 default_value = key.substr(pos+1);
912 key.erase(pos);
913 }
914
915 node = findNode(false,key);
916 if((mode & PTRPREFIX) != 0 && (node != NULL && node->type == POINTER))
917 work += "0x";
918 work += node->toString(default_value);
919
920 tail = i+1;
921 break;
922 }
923 }
924
925 work += fmt.substr(tail);
926
927 return work;
928}
929
930map<std::string, Directory *>::size_type Directory::size(map<string, Directory *>::size_type defval) const
931{
932 size_type i;
933 const_iterator scope;
934
935 if(this == NULL)
936 return defval;
937
938 i = 0;
939 scope = begin();
940 while(scope != end())
941 ++ i, ++ scope;
942
943 return i;
944}
945
Note: See TracBrowser for help on using the repository browser.