1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
|
Baltisot API
~~~~~~~~~~~~
Class Base:
----------
Every single class should at last derives from this class. It override most
of the memory usage functions. Here is the list of the functions I did override:
strdup
malloc
realloc
operator new
operator delete
free
pipe
fork
I did wrote some little and stupid memory functions. Maybe I'll later use
dlmalloc or something like this. The other function will throw an exception
if something went wrong.
If you can't write an inner-class function that has to allocate memory, use
the x* functions:
xstrdup
xmalloc
xrealloc
xfree
xpipe
xfork
Class GeneralException:
----------------------
This is the generic exception that should be thrown by everything. And then
the main() function should be written like this:
int main(int argc, char ** argv) {
try {
/* your work here */
}
catch (GeneralException e) {
cerr << _("Main function got an exception: '") << e.GetMsg() << "'.\n";
exit(-1);
}
catch (...) {
cerr << _("Unknow exception.\n") << endl;
exit(-1);
}
}
Class derivated from GeneralException:
-------------------------------------
We have the class MemoryException that will especially throw messages about
Memory allocations problems. The class IOGeneral will be thrown for every
problem about IO in general. The IOException is to be thrown by read & write
when problems occurs. The IOAgain is thrown only when the Handle which is
written or read is full and set to be non blocking. The last exception,
TaskSwitch, will be thrown by every task that want to be suspended.
You can inspire yourself from this class system to implements yours.
Class String:
------------
A very big class that can handle a large bunch of functions. Countrary of the
STL's string class, this one is a "over everything" one. As much as possible,
a String will be created. Here is the list of the constructs:
String() creates an empty string.
String(const String &) copy another string safely.
String(const char *) copy the specified pointer into the string.
String(char) creates a one-char string.
String(int) creates a string containing the string representation of the int.
String(unsigned int) same with an unsigned int.
String(long long) same with a long long.
String(unsigned long long) same with an unsigned long long.
String(double) same with a double.
Now to list of the methods.
const char * set(const char *, ...) and const char * set(const String &, ...)
They are the same as a sprintf functions, by changing the contents of the
string. They return the temporary buffer used to create the string. Beware, it
is constant, and there is a max size. If it exceeds, the result will be truncated.
const char * to_charp(size_t start = 0, ssize_t end = -1) const;
It will copy the string into a temporary buffer. Beware, it is the same as the set
function. The use of this function is depreciated. The arguments start and end
specify two offsets of extraction into the string. If end == -1, then the whole
string from the start offset will be copied.
String extract(size_t start = 0, ssize_t end = -1) const;
It will do the same as the extract function, but it will returns a String. Yet
this function is not really good since it does call to_charp. But I'll translate
it later with a better one.
char * strdup(size_t = 0, ssize_t end = -1) const;
This will produce a char *, still using the terrific to_charp function. I will soon
use the extract function, I swear.
int to_int() const;
Tries to convert the String into an int. If the string is *exactly* not an int, it
will returns 0. Even " 123" will be rejected.
double to_double() const;
The same with a double.
String to_sqdate() const;
This is a weired fonction that will convert the string "JJ/MM/AAAA" to "AAAAMMJJ".
String to_sqltime() const;
The same between "h:m" to the number h * 60 + m.
String from_sqldate() const;
String from_sqltime() const;
Those two function will revert to the original strings.
Well the four above functions are weired, but sometime useful.
double datedif(const String &) const;
This will compute the number of days between the two dates. One can be the
string "today". This code is located into the file 'datedif.c' written by
Micael Widell. Check into the file for copyright details.
bool is_date() const;
bool is_number() const;
bool is_float() const;
bool is_time() const;
These four fonctions will check if the string is actually a date, a number (int),
a float(well double too) and a time.
size_t strlen() const;
Returns the length of the string. The function is immediate because it is stored
into the object.
ssize_t strchr(char c, size_t start = 0) const;
Looks and return the first offset for a given char into a string. It will look
from the given start point. Returns -1 if the char is not found.
ssize_t strrchr(char c) const;
Look and return the last offset for a given char into a string. Returns -1
if not found.
ssize_t strstr(const String & str) const;
It will returns the position of the string str, or -1 if not found.
int strchrcnt(char c) const;
It will count the number of time of the char c into the string.
String & operator=(const String &);
Only to be safe. Well, it will safely assign one string to another. Also safe
to do s = s even if weired.
String operator+(const String &) const;
Concatens two strings to another third.
String & operator+=(const String &) const;
Add one string to the end.
bool operator!=(const String &) const;
bool operator==(const String &) const;
bool operator<=(const String &) const;
bool operator>=(const String &) const;
bool operator<(const String &) const;
bool operator>(const String &) const;
The classical comparator fonctions. This will use strcmp so the meaning is the
same. They are case sensitive. Maybe I will add a function to switch to
case unsensitive with a global variable.
char operator[](size_t i) const;
Extract one char from the string. Like the classical char * does. Well, it will
returns 0 if over the size of the string.
One note: since you can construct a String with a char * or about everything else,
you can write things like:
String s = String("Pim ") + "pam " + "poum.";
Just use your imagination.
I've also overloaded the two operators << and >> for *stream:
ostream & operator<<(ostream &, const String &);
istream & operator>>(istream &, String &);
They act as the Handles read and write function, so take a look at them.
Class Regex:
-----------
Well, to use this class, please read a bit the regex man page. You have two
construct:
Regex(const String & regex, int cflags = REG_EXTENDED, int eflags = 0)
Regex(const Regex &);
The first construct gets its meaning from the regex man page. The cflag REG_NOSUB
will always be applied. The second one is the classical copy-construct.
You can match a regex against a string using:
bool Match(const String &) const;
which will return true if the string matches the regex, and false otherwise.
The construct may return a GeneralException in case of compilation error.
There is two global regex: any and empty. any.match(s) will always be true, and
empty.match(s) will be true if s == "".
Class Variables:
---------------
Somewhat weired class. I designed it especially for the HttpServ class to handle
the POST variables strings. But you can use it for your own purpose.
The construct
Variables(int n = 0);
will initiate a stack of n empty variables. You can then use these methods:
For the methods, one variable is in the shape: "Name=value"
void SetTo(int i, const String & s);
This will set the ith variables.
String operator[](const String & s);
This will returns the value of one variable name
String operator[](int i);
This will returns the ith variable.
void Dump(Handle *, const String & format = "");
This will dump the variables stack to the Handle. Especially designed to be
used for the HttpServ. The format string is not yet usable.
int GetNb();
Returns the number of variables into the stack.
void Add(const String &);
Adds a new variable at the end of the stack.
void Del(int);
Deletes the ith variable.
void Del(const String &);
Deletes the variable given to his name.
class Handle:
------------
This class is a base one to be derivated into others. Here is the list of the
constructs:
public construct:
Handle(const Handle &);
The per-copy construct will duplicate the handle. If you close one, the other
will remains open.
protected construct:
Handle(int h);
Only for childs. Used to fill the structure.
virtual ssize_t read(void *buf, size_t count) throw (GeneralException);
virtual ssize_t write(const void *buf, size_t count) throw (GeneralException);
Self explainatory. Will never fail so the ssize_t type is only here for
compatibility.
bool IsClosed(void);
Returns true if the stream is closed. The stream will self close if it does
hit end of file.
void SetNonBlock(void);
Set the handle non blocking. Will be *VERY* useful for the Task system.
bool IsNonBlock(void);
Returns true if the handle has been set non blocking.
virtual bool CanRead();
True if the handle can read.
virtual bool CanWrite();
True if the handle can write.
virtual String GetName();
The actual name of the Handle.
virtual off_t GetSize();
The size of the input opened file. Will clearly be removed in the future.
virtual time_t GetModif();
Get the modification time of the file if possible.
void close() throw (GeneralException);
Closes the handle.
int GetHandle();
This will get the handle number. Usage deprieciated but sometime necessary.
virtual bool CanWatch();
True if the handle can be watched (when non blocking)
virtual void SetZ(int level) throw (GeneralException);
Set the Handle to go through libz. Compress will occurs if write() and
decompress will occurs if read(). Level between 0 and 9 sets the compression
ratio. SetZ(0) will do nothing. You can't revert to SetZ(0) after SetZ to a
non zero level.
I've got two operators:
Handle & operator<<(Handle &, const String &);
Handle & operator>>(Handle &, String &);
who works the same as the String >> and << operators.
When <<, the string will be dumped as exactly.
When >>, the string will be readed until \n or eof. The char \r is discarded.
The char \n, if reached, is not stored.
Class Input:
-----------
Derivated from the Handle class. Not much to say with it, nothing added.
The construct takes the file name to open. Just watch for an IOGeneral exception.
Class Stdin_t:
-------------
Designed to create the Stdin object. You can use it to input from the stdin. This
will works even if the stdin was redirected AFTER the start of the main() function.
Every Stdio_t object that will be instancied will be a dup from the current stdio
and remains as it.
Class Output:
------------
Derivated from the Handle class. Exactly as the Input class, not much to say.
Class Stdout_t & Stderr_t:
-------------------------
Exactly like the Stdin_t, and the Stdout & Stderr are the names of the global
objects that you can use.
Class Buffer:
------------
A virtual Handle that writes everything into a growing buffer. Very useful. You
can even assign one buffer to another with the operator =. Should be overflow
proof.
Class InPipe:
------------
This class is designed to hook stdout. When a further process will write to
stdout, the result will be read into the InPipe created, if it has been hooked
with the method Hook(). Designed to Hook only after a fork().
Class OutPipe:
-------------
The same but with stdin. You writes to the OutPipe, and the child process will
read it into stdin.
Class Socket:
------------
A merly complete class designed to be used on top of every socket using function.
You have the following functions:
bool SetLocal(const String & vhost, int port);
It will bind the vhost and / or the port to the socket, and return true if binded.
bool Connect(const String & host, int port);
It will connect to the specified host / port, and return true if successful,
using the vhost if binded, and local port if binded.
bool Listen();
It will begin to listen to the binded vhost and / or port, and return true if
successful.
Socket Accept() throw (GeneralException);
It will wait and return the socket of an incoming connection.
bool IsConnected();
bool IsListening();
Self explanatory.
int GetPort();
Will return the port binded to a non-previously binded Listening socket.
Class IRC:
---------
Not yet workable.
Class TaskMan:
-------------
This is a static class that will manage all the task created. The only general
purpose of this class is to run the MainLoop() function. The Task itself will
never really call any function of the TaskMan. Everything is located into the
base class Task.
Class Task:
----------
Only designed to be derivated. Let me introduce it, it's my little baby. It's
not yet really finished but I'll end it soon.
Each task has an internal state. It can be TASK_ON_HOLD, the default when created,
TASK_DONE, when the task has finished its work, and TASK_BURST.
When you design a Task, you should always have some virtual functions:
virtual String GetName();
That will return a canonical name for the task.
virtual int Do() throw (GeneralException);
That will process a "chunk" of things to do. The execution time of Do() should
be reasonable. You design it as you wish but if it does block or last a very
long time, the tasking system won't work.
You can ask the TaskMan to "wake up" your task from some events. The only events
working are the WaitFor(Task *) and WaitFor(Handle *). In the future there will
be WaitFor(pid_t) and WaitFor(timeout).
To "record" the internal process state of the method Do(), you have the protected
variable 'current' that is defaulted to 0 at start time. With that, I encourage
you to design your Do() function like this:
switch(current) {
case 0:
/* do some work */
WaitFor(something);
current = 1;
Suspend();
case 1:
/* continue your work */
WaitFor(something_else);
current = 2;
Suspend();
case 2:
...
}
If you return from the Do() function, you have to specify the state you want,
from TASK_ON_HOLD (default), TASK_DONE (task finished) and TASK_BURST.
TASK_BURST will say that at the next loop, the task should be launched even
with no events. But you should then create yourself an event because if you
don't, the burning task will overheat the TaskMan. The purpose of the TASK_BURST
is to add events that was not able to be created during the creating of the
object, or when a Task wants to signal something to another, it sets it to
TASK_BURST using the SetBurst() method.
GetState() will tells you the current state of your Task.
A task can be Stop()ed or Restar()ed, and its state of pause can be given
by IsStopped().
Each task declares itself to the TaskMan, and if not WaitedBy() another task
(Using the WaitFor(task) watches) it will be deleted when its state goes TASK_DONE.
If not, it will remains zombie until the father task deletes it.
The Suspend() function will act like a return GetState(). The only differences is
that it is done by throwing an exception, so that you can call Suspend from
within another method. You can also specify the new state by giving it as
argument of Suspend().
About the WaitFor() functions. The WaitFor(Task) is really simple. It will makes
the TaskMan to call the Do() function when the specified task has ended. The
waiting function HAS to delete the zombie. The WaitFor(Handle) accepts a flag.
It is a | of the following flags: W4_READING, W4_WRITING, W4_STICKY. In all cases
the task will be awoken if something bad happends to the handle. When a watch
over a Handle occures, the watch is removed, unless W4_STICKY.
A task can do anythings it wants, especially causing a GeneralException. Then it
will ended by the TaskMan, like if it did returned TASK_DONE.
Well I hoped I was enough clear. If not, read the source code of the following
classes:
Class CopyJob:
-------------
This task takes four parameters as creator:
CopyJob(Handle * s, Handle * d, ssize_t max = -1, bool ds = false);
The task will copy the handle s to the handle d. If max != -1 then it will copy
at most max bytes. If the bool ds is true, then the source will be deleted when
done. Not much to say. Very very very useful. Works binarly.
Class ReadJob:
-------------
ReadJob(Handle * s, Handle * d, const Regex & regex = empty);
This task will read the source handle and write the result to the destination
handle line by line, until a line matches the regex. The matching line will
also be copied.
Class HttpServ:
--------------
This class is a task that can be launched from the main function, and will never
end. It is specially designed to create distributed applications.
|