1 | // ================================================================ // |
---|
2 | // // |
---|
3 | // File : arb_handlers.cxx // |
---|
4 | // Purpose : // |
---|
5 | // // |
---|
6 | // Coded by Ralf Westram (coder@reallysoft.de) in November 2010 // |
---|
7 | // Institute of Microbiology (Technical University Munich) // |
---|
8 | // http://www.arb-home.de/ // |
---|
9 | // // |
---|
10 | // ================================================================ // |
---|
11 | |
---|
12 | #include <arb_handlers.h> |
---|
13 | #include <arb_msg.h> |
---|
14 | #include <arb_assert.h> |
---|
15 | #include <smartptr.h> |
---|
16 | #include <unistd.h> |
---|
17 | |
---|
18 | // AISC_MKPT_PROMOTE:#ifndef ARB_CORE_H |
---|
19 | // AISC_MKPT_PROMOTE:#include <arb_core.h> |
---|
20 | // AISC_MKPT_PROMOTE:#endif |
---|
21 | |
---|
22 | static FILE *arberr = stderr; |
---|
23 | static FILE *arbout = stdout; |
---|
24 | |
---|
25 | static void to_arberr(const char *msg) { |
---|
26 | fflush(arbout); |
---|
27 | fprintf(arberr, "%s\n", msg); |
---|
28 | fflush(arberr); |
---|
29 | } |
---|
30 | static void to_arbout(const char *msg) { |
---|
31 | fprintf(arbout, "%s\n", msg); |
---|
32 | } |
---|
33 | |
---|
34 | // ------------------------- |
---|
35 | // ARB_arbout_status |
---|
36 | |
---|
37 | const int HEIGHT = 12; // 12 can be devided by 2, 3, 4 (so subtitles tend to be at start of line) |
---|
38 | const int WIDTH = 70; |
---|
39 | const char CHAR = '.'; |
---|
40 | |
---|
41 | class BasicStatus : virtual Noncopyable { |
---|
42 | int openCount; |
---|
43 | char *subtitle; |
---|
44 | int printed; |
---|
45 | const char *cursor; |
---|
46 | |
---|
47 | public: |
---|
48 | BasicStatus() : openCount(0) {} |
---|
49 | ~BasicStatus() { if (openCount) close(); } |
---|
50 | |
---|
51 | void open(const char *title) { |
---|
52 | arb_assert(++openCount <= 1); |
---|
53 | |
---|
54 | fprintf(arbout, "Progress: %s\n", title); |
---|
55 | printed = 0; |
---|
56 | cursor = NULL; |
---|
57 | subtitle = NULL; |
---|
58 | } |
---|
59 | void close() { |
---|
60 | freenull(subtitle); |
---|
61 | fprintf(arbout, "[done]\n"); |
---|
62 | arb_assert(--openCount >= 0); |
---|
63 | fflush(arbout); |
---|
64 | } |
---|
65 | |
---|
66 | int next_LF() const { return printed-printed%WIDTH+WIDTH; } |
---|
67 | |
---|
68 | void set_subtitle(const char *stitle) { |
---|
69 | arb_assert(openCount == 1); |
---|
70 | if (cursor) { |
---|
71 | int offset = cursor - subtitle; |
---|
72 | subtitle[strlen(subtitle)-1] = 0; |
---|
73 | freeset(subtitle, GBS_global_string_copy("%s/%s}", subtitle, stitle)); |
---|
74 | cursor = subtitle+offset; |
---|
75 | } |
---|
76 | else { |
---|
77 | freeset(subtitle, GBS_global_string_copy("{%s}", stitle)); |
---|
78 | cursor = subtitle; |
---|
79 | } |
---|
80 | } |
---|
81 | void set_gauge(double gauge) { |
---|
82 | arb_assert(openCount == 1); |
---|
83 | |
---|
84 | int wanted = int(gauge*WIDTH*HEIGHT); |
---|
85 | int nextLF = next_LF(); |
---|
86 | |
---|
87 | if (printed<wanted) { |
---|
88 | while (printed<wanted) { |
---|
89 | if (cursor && cursor[0]) { |
---|
90 | fputc(*cursor++, arbout); |
---|
91 | } |
---|
92 | else { |
---|
93 | cursor = 0; |
---|
94 | fputc(CHAR, arbout); |
---|
95 | } |
---|
96 | printed++; |
---|
97 | if (printed == nextLF) { |
---|
98 | fprintf(arbout, " [%5.1f%%]\n", printed*100.0/(WIDTH*HEIGHT)); |
---|
99 | nextLF = next_LF(); |
---|
100 | } |
---|
101 | } |
---|
102 | fflush(arbout); |
---|
103 | #if defined(DEBUG) |
---|
104 | // usleep(25000); // uncomment to see slow status |
---|
105 | #endif |
---|
106 | } |
---|
107 | } |
---|
108 | }; |
---|
109 | |
---|
110 | static BasicStatus status; |
---|
111 | |
---|
112 | static void basic_openstatus(const char *title) { status.open(title); } |
---|
113 | static void basic_closestatus() { status.close(); } |
---|
114 | static bool basic_set_title(const char */*title*/) { return false; } |
---|
115 | static bool basic_set_subtitle(const char *stitle) { status.set_subtitle(stitle); return false; } |
---|
116 | static bool basic_set_gauge(double gauge) { status.set_gauge(gauge); return false; } |
---|
117 | static bool basic_user_abort() { return false; } |
---|
118 | |
---|
119 | static arb_status_implementation ARB_arbout_status = { |
---|
120 | AST_FORWARD, |
---|
121 | basic_openstatus, |
---|
122 | basic_closestatus, |
---|
123 | basic_set_title, |
---|
124 | basic_set_subtitle, |
---|
125 | basic_set_gauge, |
---|
126 | basic_user_abort |
---|
127 | }; |
---|
128 | |
---|
129 | static arb_handlers arbout_handlers = { |
---|
130 | to_arberr, |
---|
131 | to_arbout, |
---|
132 | to_arbout, |
---|
133 | ARB_arbout_status, |
---|
134 | }; |
---|
135 | |
---|
136 | arb_handlers *active_arb_handlers = &arbout_handlers; // default-handlers |
---|
137 | |
---|
138 | void ARB_install_handlers(arb_handlers& handlers) { active_arb_handlers = &handlers; } |
---|
139 | |
---|
140 | void ARB_redirect_handlers_to(FILE *errStream, FILE *outStream) { |
---|
141 | arberr = errStream; |
---|
142 | arbout = outStream; |
---|
143 | } |
---|