.
[sfinx.git] / include / elements.H
blob94c79c62cfeedebcbb96ef389875f9ac42fb5663
2  /*
3   *   Copyright (C) 2007, Rus V. Brushkoff, All rights reserved.
4   */
6 // TODO:
7 //        - ËÏÎÃÅÐÃÉÑ ÂÕÆÅÒÁ : buf->get/put(sfinx_t)
8 //        - rewrite using text or binary XML (ebml) data format
9 //        - fix all id's and sizes to 64 bit values
11 #ifndef _ELEMENTS_H_
12 #define _ELEMENTS_H_
14 #include <arpa/inet.h>
15 #include <string.h>
16 #include <platform.H>
17 #include <vector>
18 #include <typeinfo>
20 using namespace std;
22 #include <F_Log.H>
23 #include <proto.H>
25 using namespace F;
27 typedef unsigned int u32_t;
28 typedef signed int s32_t;
29 typedef unsigned short u16_t;
30 typedef signed short s16_t;
31 typedef unsigned long long u64_t;
32 typedef signed long long s64_t;
33 typedef unsigned char u8_t;
34 typedef signed char s8_t;
36 // ÉÄÅÎÔÉÆÉËÁÔÏÒÙ ÏÂØÅËÔÏ×
37 typedef u32_t sfinx_tid_t;
38 typedef u64_t sfinx_id_t;
39 typedef u64_t sfinx_size_t;
40 // ÔÉÐÙ ÏÂØÅËÔÏ×
41 typedef u32_t sfinx_type_t;
43 class sfinx_t {
45     // ÐÏËÁ ÎÅ ÎÕÖÎÙ
46     sfinx_t(const sfinx_t &st) { bug(); }
47     sfinx_t &operator=(const sfinx_t &st) { return operator=(&st); }
48     sfinx_t &operator=(const sfinx_t *st) { bug(); return *this; }
50     // ÉÓÐÏÌØÚÕÅÔÓÑ ÄÌÑ ÐÅÒÅÄÁÞÉ ÏÂØÅËÔÁ ÞÅÒÅÚ ÂÉÎÁÒÎÙÊ ÂÕÆÅÒ
51     // ×ÏÚ×ÒÁÝÁÅÔ ÒÁÚÍÅÒ ÐÏÌÏÖÅÎÎÙÈ × ÂÕÆÅÒ ÄÁÎÎÙÈ
52     virtual sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) = 0;
53     // ÉÓÐÏÌØÚÕÅÔÓÑ ÄÌÑ ×ÏÓÓÔÁÎÏ×ÌÅÎÉÑ ÏÂØÅËÔÁ ÉÚ ÂÉÎÁÒÎÏÇÏ ÂÕÆÅÒÁ
54     // ×ÏÚ×ÒÁÝÁÅÔ ÒÁÚÍÅÒ ×ÙÎÕÔÙÈ ÉÚ ÂÕÆÅÒÁ ÄÁÎÎÙÈ
55     virtual sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) = 0;
57   protected:
59     sfinx_size_t size_; // ÒÁÚÍÅÒ ÏÂØÅËÔÁ × ÂÁÊÔÁÈ
60     sfinx_tid_t tid_; // sfinx element type id
61     void copy_size_tid(const sfinx_t *s) { size_ = s->size_; tid_ = s->tid_; } 
63   public:
65     // copy object
66     virtual void copy(const sfinx_t *st) = 0;
68     sfinx_t(sfinx_tid_t _tid) { tid_ = _tid; size_ = 0; }
69     virtual ~sfinx_t() { }
71     sfinx_id_t tid() { return tid_; }
72     void tid(sfinx_id_t t) { tid_ = t; }
73     // ÔÅËÓÔÏ×ÏÅ ÉÍÑ ÔÉÐÁ
74     virtual const char *sidstr() { return "generic sfinx object"; }
75     // update size for object
76     virtual sfinx_size_t size() = 0;
77     // try copy object to string
78     virtual bool get(string &s) { debug("class - %s", typeid(*this).name()); bug(); return false; }
79     // try copy object to u32_t
80     virtual bool get(u32_t *v) { debug("class - %s", typeid(*this).name()); bug(); return false; }
81     // try to copy object from string
82     virtual bool set(string &s) { debug("class - %s", typeid(*this).name()); bug(); return false; }
83     // try to copy object from u32_t
84     virtual bool set(u32_t v) { debug("class - %s", typeid(*this).name()); bug(); return false; }
86     friend class sfinx_pair_t;
87     friend class sfinx_elements;
90 static sfinx_t *make_sfinx_element(sfinx_tid_t tid);
92 class sfinx_8bit_t : public sfinx_t {
93   u8_t val_;
94   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
95     if (object_size_in_buf) {
96        val_ = buf[0];
97        return size();
98    } else
99        return 0;
101   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
102     if (available_buf_space) {
103       buf[0] = val_;
104       return size();
105    } else
106       return 0;
108   public:
109   void copy(const sfinx_t *s) {
110     if (!dynamic_cast<const sfinx_8bit_t *>(s))
111       bug();
112     copy_size_tid(s);
113     val_ = ((const sfinx_8bit_t *)s)->val_;
115     sfinx_8bit_t() : sfinx_t(SFINX_ELEMENT_8BIT) { }
116     sfinx_8bit_t(sfinx_tid_t _tid) : sfinx_t(_tid)  { }
117     sfinx_size_t size() { return (size_ = sizeof(u8_t)); }
118     u8_t get() { return val_; }
119     void set(u8_t v) { val_ = v; size_ = sizeof(u8_t); }
123 class sfinx_8bit_vector_t : public sfinx_t {
124   vector <u8_t> val;
125   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
126     clear();
127     for (sfinx_size_t i = 0; i < object_size_in_buf; i++)
128       val.push_back(buf[i]);
129     return size();
131   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
132     if (available_buf_space < size_)
133       return 0;
134     for (sfinx_size_t i = 0; i < size_; i++)
135       buf[i] = val[i];
136     return size();
138   public:
139   void copy(const sfinx_t *s) {
140     if (!dynamic_cast<const sfinx_8bit_vector_t *>(s))
141       bug();
142     clear();
143     copy_size_tid(s);
144     for (sfinx_size_t i = 0; i < ((const sfinx_8bit_vector_t *)s)->val.size(); i++)
145       val.push_back(((const sfinx_8bit_vector_t *)s)->val[i]);
147     sfinx_8bit_vector_t(sfinx_tid_t _tid = SFINX_ELEMENT_8BIT_VECTOR) : sfinx_t(_tid) { }
148     void clear() { val.clear(); size_ = 0; }
149     void add(u8_t v) { val.push_back(v); size_+= sizeof(u8_t); }
150     bool set(u8_t *b, sfinx_size_t len) { return (get(b, len) != len); }
151     u8_t get(sfinx_size_t idx) { return val[idx]; }
152     sfinx_size_t size() { return (size_ = val.size()); }
153     sfinx_size_t len() { return size(); }
157 class sfinx_32bit_t : public sfinx_t {
158   u32_t val_;
159   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
160     if (object_size_in_buf < sizeof(u32_t))
161       return 0;
162     val_ = ((u32_t *)buf)[0];
163     return size();
165   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
166     if (available_buf_space < sizeof(u32_t))
167       return 0;
168     ((u32_t *)buf)[0] = val_;
169     return size();
171   public:
172   void copy(const sfinx_t *s) {
173     if (!dynamic_cast<const sfinx_32bit_t *>(s))
174       bug();
175     copy_size_tid(s);
176     val_ = ((const sfinx_32bit_t *)s)->val_;
178     sfinx_32bit_t() : sfinx_t(SFINX_ELEMENT_32BIT) { }
179     sfinx_32bit_t(sfinx_tid_t _tid) : sfinx_t(_tid)  { }
180     u32_t get() { return val_; }
181     bool get(u32_t *v) { *v = val_; return 0; }
182     bool set(u32_t v) { val_ = v; size(); return 0; }
183     sfinx_size_t size() { return (size_ = sizeof(u32_t)); }
186 #define IBPP_LINUX
187 #include <ibpp.h>
189 using namespace IBPP;
191 class sfinx_timestamp_t : public Timestamp {
192   public:
193     sfinx_timestamp_t() : Timestamp() { mDate = IBPP::MinDate; mTime = 0; }
194     //sfinx_timestamp_t(const Timestamp &t) : Timestamp(t) { }
195     sfinx_size_t size() { return (sizeof(mDate) + sizeof(mTime)); }
196     sfinx_size_t get(u8_t *buf) {
197       u32_t date, time;
198       memcpy(&date, buf, sizeof(date));
199       memcpy(&time, buf + sizeof(date), sizeof(time));
200       SetDate(date);
201       SetTime(time);
202       return size();
203    }
204     sfinx_size_t put(u8_t *buf) {
205       u32_t date, time;
206       date = GetDate();
207       time = GetTime();
208       memcpy(buf, &date, sizeof(date));
209       memcpy(buf + sizeof(date), &time, sizeof(time));
210       return size();
211    }
212     void set(time_t t) {
213       tm *loctime = localtime(&t);
214       if (!IBPP::itod(&mDate, loctime->tm_year + 1900, loctime->tm_mon + 1, loctime->tm_mday))
215         log("sfinx_timestamp_t", "Out of range");
216       IBPP::itot(&mTime, loctime->tm_hour, loctime->tm_min, loctime->tm_sec, 0);
217    }
220 // make some libsfinx include
221 // serialize/deserialize methods
222 extern sfinx_size_t get(sfinx_id_t *v, u8_t *buf);
223 extern sfinx_size_t get(sfinx_type_t *v, u8_t *buf);
224 extern sfinx_size_t get(string *v, u8_t *buf);
225 extern sfinx_size_t get(u8_t *v, u8_t *buf);
226 extern sfinx_size_t get(float *v, u8_t *buf);
227 extern sfinx_size_t put(sfinx_id_t &v, u8_t *buf);
228 extern sfinx_size_t put(sfinx_type_t &v, u8_t *buf);
229 extern sfinx_size_t put(string &v, u8_t *buf);
230 extern sfinx_size_t put(u8_t &v, u8_t *buf);
231 extern sfinx_size_t put(float &v, u8_t *buf);
233 class sfinx_object_t {
234   public:
235     sfinx_id_t id, slice_id;
236     sfinx_type_t type;
237     string name, path_name, description;
238     sfinx_timestamp_t ctime, etime;
239     sfinx_object_t() { id = type = 0; }
240     sfinx_object_t(sfinx_type_t t, sfinx_id_t i, sfinx_id_t s = 0) {
241       type = t;
242       id = i;
243       slice_id = s;
244    }
245     sfinx_object_t(sfinx_type_t t, sfinx_id_t i, sfinx_id_t s, const char *n, sfinx_timestamp_t &ct,
246       sfinx_timestamp_t &et) {
247         type = t;
248         id = i;
249         slice_id = s;
250         name = n;
251         ctime = ct;
252         etime = et;
253    }
254     bool cmp(sfinx_object_t *o) {
255       if ((o->id == id) && (o->type == type) && (o->slice_id == o->slice_id))
256         return false;
257       return true;
258    }
259     sfinx_size_t size() { return (2 * sizeof(sfinx_id_t) + sizeof(sfinx_type_t) + name.size() + 1 +
260       path_name.size() + 1 + description.size() + 1 + ctime.size() + etime.size()); }
261     sfinx_size_t get(u8_t *buf) {
262       u8_t *t = buf;
263       buf += ::get(&id, buf);
264       buf += ::get(&slice_id, buf);
265       buf += ::get(&type, buf);
266       buf += ::get(&name, buf);
267       buf += ::get(&path_name, buf);
268       buf += ::get(&description, buf);
269       buf += ctime.get(buf);
270       buf += etime.get(buf);
271       return (buf - t);
272    }
273     u32_t put(u8_t *buf) {
274       u8_t *t = buf;
275       buf += ::put(id, buf);
276       buf += ::put(slice_id, buf);
277       buf += ::put(type, buf);
278       buf += ::put(name, buf);
279       buf += ::put(path_name, buf);
280       buf += ::put(description, buf);
281       buf += ctime.put(buf);
282       buf += etime.put(buf);      
283       return (buf - t);
284    }
287 extern char tag2char(sfinx_object_t &tag);
288 extern const char *tagtype2str(sfinx_object_t &tag);
290 class sfinx_slice_t : public sfinx_t {
292   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
293     if (available_buf_space < size())
294       return 0;
295     u8_t *t = buf;
296     buf += ::put(id, buf);
297     buf += ::put(parent_id, buf);
298     buf += ::put(name_, buf);
299     buf += ::put(directory_, buf);
300     buf += ::put(description_, buf);
301     buf += ::put(parent_name_, buf);
302     buf += ctime.put(buf);
303     buf += etime.put(buf);
304     // objs
305     u32_t l = objs.size();
306     buf += ::put(l, buf);
307     for (u32_t i = 0; i < l; i++)
308       buf += objs[i].put(buf);
309     return (buf - t);
311   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
312     u8_t *t = buf;
313     buf += ::get(&id, buf);
314     buf += ::get(&parent_id, buf);
315     buf += ::get(&name_, buf);
316     buf += ::get(&directory_, buf);
317     buf += ::get(&description_, buf);
318     buf += ::get(&parent_name_, buf);
319     buf += ctime.get(buf);
320     buf += etime.get(buf);
321     // objs
322     u32_t l;
323     buf += ::get(&l, buf);
324     for (u32_t i = 0; i < l; i++) {
325       sfinx_object_t obj;
326       buf += obj.get(buf);
327       objs.push_back(obj);
328    }
329    // hmm, ÐÒÏ×ÅÒËÁ ÌÉÛØ × ËÏÎÃÅ
330     if ((sfinx_size_t)(buf - t) > object_size_in_buf)
331       return 0;
332     return size();
335   public:
337   void copy(const sfinx_t *s) {
338       if (!dynamic_cast<const sfinx_slice_t *>(s))
339         bug();
340       copy_size_tid(s);
341       const sfinx_slice_t *s_ = (const sfinx_slice_t *)s;
342       id = s_->id;
343       name_ = s_->name_;
344       directory_ = s_->directory_;
345       parent_name_ = s_->parent_name_;
346       description_ = s_->description_;
347       parent_id = s_->parent_id;
348       ctime = s_->ctime;
349       etime = s_->etime;
350       objs = s_->objs;
352   sfinx_id_t id;
353   string name_, directory_, description_, parent_name_;
354   sfinx_id_t parent_id;
355   sfinx_timestamp_t ctime, etime;
356   vector <sfinx_object_t> objs; // ×ÌÏÖÅÎÎÙÅ × ÓÌÁÊÓ ÏÂØÅËÔÙ
357   sfinx_object_t slice_obj;
359   const char *name() { return name_.c_str(); }
360   const char *directory() { return directory_.c_str(); }
361   const char *description() { return description_.c_str(); }
362   const char *parent_name() { return parent_name_.c_str(); }
363   sfinx_object_t *object() {
364     slice_obj.ctime = ctime;
365     slice_obj.etime = etime;
366     slice_obj.name = name_;
367     slice_obj.type = SFINX_SLICE_OBJECT;
368     slice_obj.slice_id = slice_obj.id = id;
369     slice_obj.path_name = directory_;
370     slice_obj.description = description_;
371     return &slice_obj;
372   }
374   void add(sfinx_object_t &obj) { objs.push_back(obj); }
375   void name(const char *s) { name_ = s; size(); }
376   void directory(const char *d) { directory_ = d; size(); }
377   void description(const char *s) { description_ = s; size(); }
378   void parent_name(const char *s) { parent_name_ = s; size(); }
380   sfinx_slice_t(sfinx_tid_t tid = SFINX_ELEMENT_SLICE) : sfinx_t(tid) {
381     parent_id = id = 0;
382     size();
384   sfinx_slice_t(sfinx_slice_t *s) : sfinx_t(SFINX_ELEMENT_SLICE) { copy(s); }
385   sfinx_slice_t(sfinx_id_t id_, string &name__, string &directory__, string &description__,
386     string &parent_name__, sfinx_id_t parent_id, sfinx_timestamp_t ctime_, sfinx_timestamp_t etime_,
387       sfinx_tid_t tid = SFINX_ELEMENT_SLICE) : sfinx_t(tid), id(id_), name_(name__),
388       directory_(directory__), description_(description__), parent_name_(parent_name__),
389       parent_id(parent_id), ctime(ctime_), etime(etime_) { size(); }
390   sfinx_size_t size() {
391      u32_t s = sizeof(u32_t); // ÄÌÉÎÁ ÓÞÅÔÞÉËÁ ÏÂØÅËÔÏ×
392      for (u32_t i = 0; i < objs.size(); i++)
393        s += objs[i].size();
394      return (size_ = sizeof(id) + name_.size() + 1 + directory_.size() + 1 +
395        description_.size() + 1 + parent_name_.size() + 1 + sizeof(parent_id) + ctime.size() +
396        etime.size() + s);
398   friend class sfinx_slice_vector_t;
401 class sfinx_slice_vector_t : public sfinx_t {
403   vector <sfinx_slice_t *> slices;  
405   sfinx_size_t size() {
406     size_ = 0;
407     for (u32_t i = 0; i < slices.size(); i++)
408       size_ += slices[i]->size();
409     return size_;
411   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
412     u32_t offset = 0;
413     for (u32_t i = 0; i < slices.size(); i++) {
414       if (slices[i]->put(buf + offset, available_buf_space) != slices[i]->size())
415         return 0;
416       available_buf_space -= slices[i]->size();
417       offset += slices[i]->size();
418    }
419     return size();
421   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
422     clear();
423     while (object_size_in_buf) {
424       sfinx_slice_t *slice = new sfinx_slice_t;
425       sfinx_size_t res = slice->get(buf + size(), object_size_in_buf);
426       if (res != slice->size()) {
427         delete slice;
428         return 0;
429      }
430       add(slice);
431       if (object_size_in_buf < slice->size())
432         return 0;
433       object_size_in_buf -= slice->size();
434    }
435     return size();
437   void clear() {
438     for (u32_t i = 0; i < slices.size(); i++)
439       delete slices[i];
440     slices.clear();
441     size_ = 0;
443   public:
444   void copy(const sfinx_t *s) {
445     const sfinx_slice_vector_t *src = dynamic_cast<const sfinx_slice_vector_t *>(s);
446     if (!src)
447       bug();
448     clear();
449     copy_size_tid(src);
450     for (u32_t i = 0; i < src->slices.size(); i++) {
451       sfinx_slice_t *slice = new sfinx_slice_t(src->slices[i]);
452       slices.push_back(slice);
453    }
455     sfinx_slice_vector_t(sfinx_tid_t tid = SFINX_ELEMENT_SLICE_VECTOR) : sfinx_t(tid) { }
456     ~sfinx_slice_vector_t() { clear(); }
457     void add(sfinx_slice_t *slice) {
458       sfinx_slice_t *s = new sfinx_slice_t(slice);
459       slices.push_back(s); // ËÏÐÉÒÕÅÍ ÏÂØÅËÔ
460       size_ += slice->size();
461    }
462     void add(sfinx_slice_t &slice) { add(&slice); }
463     u32_t len() { return slices.size(); }
464     sfinx_slice_t *get(u32_t idx) { return slices[idx]; }
465     sfinx_slice_t *find(u32_t id) {
466       for (u32_t i = 0; i < slices.size(); i++) {
467         if (id == slices[i]->id)
468           return slices[i];
469      }
470       return 0;
471    }
474 class sfinx_string_t : public sfinx_t {
475   string s;
476   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
477     if (available_buf_space < (s.size() + 1))
478       return 0;
479     if (!s.size())
480       buf[0] = 0;
481     else
482       strcpy((char *)buf, s.c_str());
483     return size();
485   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
486     s = (char *) buf;
487     return size();
489   public:
490   void copy(const sfinx_t *s_) {
491     if (!dynamic_cast<const sfinx_string_t *>(s_))
492       bug();
493     copy_size_tid(s_);
494     s = ((const sfinx_string_t *)s_)->s;
496     sfinx_size_t size() { return (size_ = s.size() + 1); }
497     sfinx_string_t(sfinx_tid_t tid = SFINX_ELEMENT_STRING) : sfinx_t(tid) { size_ = 1; }
498     sfinx_string_t(const char *s_) : sfinx_t(SFINX_ELEMENT_STRING) {
499       s = s_;
500       size();
501    }
502     const char *c_str() { return s.c_str(); }
503     bool get(string &s_) { s_ = s; return true; }
504     bool set(string &s_) {
505       if (s_.size())
506         s = s_;
507       else
508          s.clear();
509       size();
510       return true;
511    }
512     bool set(const char *s_) {
513       if (s_)
514         s = s_;
515       else
516         s.clear();
517       size();
518       return true;
519    }
522 // ÐÁÒÁ ÅÌÅÍÅÎÔÏ× int -> sfinx_t
523 class sfinx_pair_t : public sfinx_t {
524     u32_t key_;
525     sfinx_t *element;
526   void clear() {
527     key_ = SFINX_KEY_UNASSIGNED;
528     if (element)
529       delete element;
530     element = 0;
531     size_ = 0;
533   sfinx_size_t size() { return (size_ = element->size() + 2 * sizeof(u32_t)); } // + element id
534   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
535     if (available_buf_space < size())
536       return 0;
537     buf += ::put(key_, buf);
538     sfinx_tid_t eid = element->tid();
539     buf += ::put(eid, buf);
540     //debug("eid - %x, size - %d, space - %d", eid, size(), available_buf_space);
541     if (!element->put(buf, available_buf_space - (sizeof(eid) + sizeof(key_))))
542       return 0;
543     return size();
545   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
546     clear();
547     buf += ::get(&key_, buf);
548     sfinx_tid_t eid;
549     buf += ::get(&eid, buf);
550     //debug("eid - %x, size_in_buf - %d", eid, object_size_in_buf);
551     if (!eid)
552       bug();
553     element = make_sfinx_element(eid);
554     if (element) {
555       element->get(buf, object_size_in_buf -  (sizeof(eid) + sizeof(key_)));
556       return size();
557    }
558     return 0;
560   public:
561   void copy(const sfinx_t *s) {
562     const sfinx_pair_t *src = dynamic_cast<const sfinx_pair_t *>(s);
563     if (!src)
564       bug();
565     clear();
566     copy_size_tid(src);
567     element = make_sfinx_element(src->element->tid());
568     if (!element)
569       bug();
570     element->copy(src->element);
571     key_ = src->key_;
573     sfinx_pair_t(sfinx_tid_t tid = SFINX_ELEMENT_PAIR) : sfinx_t(tid) {
574       key_ = SFINX_KEY_UNASSIGNED; element = 0;
575    }
576     u32_t key() { return key_; }
577     ~sfinx_pair_t() { clear(); }
578     bool get(u32_t k, uint32_t *v) {
579       if (k != key_)
580         return false;
581       return element->get(v);
582    }
583     bool get(u32_t k, string &s) {
584       if (k != key_)
585         return false;
586       return element->get(s);
587    }
588     bool get(u32_t k, sfinx_t **el) {
589       if (k != key_)
590         return false;
591       *el = element;
592       return true;
593    }
594     bool set(u32_t k, sfinx_t &e) { return set(k, &e); }
595     bool set(u32_t k, sfinx_t *e) {
596       // ÎÅÐÌÏÈÏ ÂÙ ÐÒÏ×ÅÒÉÔØ ÞÔÏ id() != SFINX_ELEMENT_PAIR
597       clear();
598       element = make_sfinx_element(e->tid()); // ÆÁÂÒÉËÁ ÐÕÓÔÙÈ ÅÌÅÍÅÎÔÏ× ÏÐÒ. ÔÉÐÁ
599       if (element) {
600         element->copy(e); // ÔÉÐÁ ËÏÎÔÓÒÕËÔÏÒ ËÏÐÉÒÏ×ÁÎÉÑ
601         key_ = k;
602         size();
603         return 0;
604      }
605        return 1;
606    }
607     bool set(u32_t k, string &s) {
608       clear();
609       element = new sfinx_string_t;
610       if (element) {
611         key_ = k;
612         if (!element->set(s))
613           return false;
614         size();
615         return true;
616      }
617       return false;
618    }
619     bool set(u32_t k, const char *s) { string t(s); return set(k, t); }
620     bool set(u32_t k, u32_t v) {
621       clear();
622       element = new sfinx_32bit_t;
623       element->set(v);
624       key_ = k;
625       size();
626       return true;
627   }
628    friend class sfinx_pair_vector_t;
631 // ÎÁÂÏÒ ÐÁÒ ÅÌÅÍÅÎÔÏ× int -> sfinx_t
632 class sfinx_pair_vector_t : public sfinx_t {
633   vector <sfinx_pair_t *> pairs;
634   sfinx_size_t size() {
635     size_ = 0;
636     for (u32_t i = 0; i < pairs.size(); i++)
637       size_ += pairs[i]->size();
638     return size_;
640   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
641     int32_t space = available_buf_space;
642     u32_t offset = 0;
643     for (u32_t i = 0; i < pairs.size(); i++) {
644       u32_t sz = pairs[i]->put(buf + offset, available_buf_space - offset);
645       if (!sz || ((space - sz) < 0))
646         bug();
647       space -= sz;
648       offset += sz;
649    }
650     return offset;
652   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
653     int32_t space = object_size_in_buf;
654     int32_t offset = 0;
655     clear();
656     while (space) {
657       sfinx_pair_t *pair = new sfinx_pair_t; // id ÔÅÒÑÅÍ
658       int32_t sz = pair->get(buf + offset, object_size_in_buf - offset);
659       offset += sz;
660       if (!sz || (space - sz) < 0)
661         bug();
662       pairs.push_back(pair);
663       size_ += pair->size();
664       space -= sz;
665       //debug("offset - %d, all_size - %d, space - %d", offset, object_size_in_buf, space);
666    }
667     return offset;
669   public:
670   void clear() {
671     for (u32_t i = 0; i < pairs.size(); i++)
672       delete pairs[i];
673     pairs.clear();
674     size_ = 0;
676   void copy(const sfinx_t *s) {
677     const sfinx_pair_vector_t *src = dynamic_cast<const sfinx_pair_vector_t *>(s);
678     if (!src)
679       bug();
680     clear();
681     copy_size_tid(src);
682     for (u32_t i = 0; i < src->pairs.size(); i++)
683       if (!add(src->pairs[i]))
684         bug();
686     sfinx_pair_t *find(u32_t k) {
687       for (u32_t i = 0; i < pairs.size(); i++) {
688         if (k == pairs[i]->key())
689           return pairs[i];
690      }
691       return 0;
693   u32_t len() { return pairs.size(); }
694   bool find(u32_t k, u32_t *idx) {
695     for (u32_t i = 0; i < pairs.size(); i++) {
696       if (k == pairs[i]->key()) {
697         *idx = i;
698         return 1;
699      }
700    }
701     return 0;
703   sfinx_pair_vector_t(sfinx_tid_t tid = SFINX_ELEMENT_PAIR_VECTOR) : sfinx_t(tid) { }
704   bool add(sfinx_pair_t *p) {
705     if (find(p->key()))
706       return false;
707     sfinx_pair_t *pair = new sfinx_pair_t(p->tid());
708     pair->copy(p);
709     pairs.push_back(pair);
710     size_ += pair->size();
711     return true;
713   // returns false on error (key exists)
714   bool add(u32_t k, sfinx_t *e) {
715     if (find(k))
716       return false;
717     sfinx_pair_t *p = new sfinx_pair_t;
718     if (p->set(k, e)) {
719       delete p;
720       return false;
721     } else {
722       pairs.push_back(p);
723       size_ += p->size();
724       return true;
725     }
727   // return false if key not found
728   bool get(u32_t k, uint32_t *v) {
729    sfinx_pair_t *pair = find(k);
730    if (!pair)
731      return false;
732    return pair->get(k, v);
734   bool get(u32_t k, string &s) {
735    sfinx_pair_t *pair = find(k);
736    if (!pair)
737      return false;
738    return pair->get(k, s);      
741 //    bool get(u32_t k, sfinx_t *s) {
742 //    sfinx_pair_t *pair = find(k);
743 //     if (!pair)
744 //       return false;
745 //     return pair->get(k, s);
746 //   }
748   bool add(u32_t k, uint32_t v) {
749     if (find(k))
750       return false;
751     sfinx_pair_t *pair = new sfinx_pair_t;
752     pair->set(k, v);
753     add(pair);
754     return true;
756   bool add(u32_t k, string &s) {
757     if (find(k))
758       return false;
759     sfinx_pair_t *pair = new sfinx_pair_t;
760     pair->set(k, s);
761     add(pair);
762     return true;
764   bool add(u32_t k, const char *s) { string t(s); return add(k, t); }
767 class sfinx_file_t : public sfinx_t {
768   sfinx_size_t size() {
769       u32_t tags_size = sizeof(u32_t); // obj counter
770       for (u32_t i = 0; i < tags.size(); i++)
771         tags_size += tags[i].size();
772       return (size_ = sizeof(sfinx_id_t) + mtag.size() + 2 * sizeof(sfinx_size_t) + tags_size +
773         name.size() + 1 + orig_name.size() + 1 + title.size() + 1 + authority.size() + 1 +
774         description.size() + 1 + comments.size() + 1 + ctime.size() + etime.size() +
775         4 * sizeof(u8_t) + mimetype.size() + 1 + csum.size() + 1 + compressed_csum.size() + 1);
777   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
778     if (size() > available_buf_space)
779       return 0;
780     buf += ::put(id, buf);
781     u8_t v = is_directory;
782     buf += ::put(v, buf);
783     v = sorted_location;
784     buf += ::put(v, buf);
785     v = store_compressed;
786     buf += ::put(v, buf);
787     v = generate_csum;
788     buf += ::put(v, buf);
789     buf += mtag.put(buf);
790     buf += ::put(fsize, buf);
791     buf += ::put(compressed_fsize, buf);
792     u32_t t = tags.size();
793     buf += ::put(t, buf);
794     for (u32_t i = 0; i < tags.size(); i++)
795       buf += tags[i].put(buf);
796     buf += ::put(name, buf);
797     buf += ::put(orig_name, buf);
798     buf += ::put(title, buf);
799     buf += ::put(authority, buf);
800     buf += ::put(description, buf);
801     buf += ::put(comments, buf);
802     buf += ::put(mimetype, buf);
803     buf += ::put(csum, buf);
804     buf += ::put(compressed_csum, buf);
805     buf += ctime.put(buf);
806     buf += etime.put(buf);
807     return size_;
809   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
810     u8_t *tmp = buf;
811     clear();
812     buf += ::get(&id, buf);
813     u8_t v;
814     buf += ::get(&v, buf);
815     is_directory = v;
816     buf += ::get(&v, buf);
817     sorted_location = v;
818     buf += ::get(&v, buf);
819     store_compressed = v;
820     buf += ::get(&v, buf);
821     generate_csum = v;
822     buf += mtag.get(buf);
823     buf += ::get(&fsize, buf);
824     buf += ::get(&compressed_fsize, buf);
825     u32_t tags_size;
826     buf += ::get(&tags_size, buf);
827     for (u32_t i = 0; i < tags_size; i++) {
828       sfinx_object_t o;
829       buf += o.get(buf);
830       tags.push_back(o);
831    }
832     buf += ::get(&name, buf);
833     buf += ::get(&orig_name, buf);
834     buf += ::get(&title, buf);
835     buf += ::get(&authority, buf);
836     buf += ::get(&description, buf);
837     buf += ::get(&comments, buf);
838     buf += ::get(&mimetype, buf);
839     buf += ::get(&csum, buf);
840     buf += ::get(&compressed_csum, buf);
841     buf += ctime.get(buf);
842     buf += etime.get(buf);
843     if (size() != (sfinx_size_t)(buf - tmp))
844       bug();
845     return size_;
847   public:
848   void clear() {
849     tags.clear();
850     id = mtag.type = mtag.id = fsize = 0;
851     is_directory = false;
852     size_ = 0;
853  }  void copy(const sfinx_t *s) {
854     const sfinx_file_t *src = dynamic_cast<const sfinx_file_t *>(s);
855     if (!src)
856       bug();
857     clear();
858     ((sfinx_t *)s)->size();
859     copy_size_tid(src);
860     id = src->id;
861     mtag = src->mtag;
862     fsize = src->fsize;
863     compressed_fsize = src->compressed_fsize;
864     name = src->name;
865     orig_name = src->orig_name;
866     title = src->title;
867     authority = src->authority;
868     description = src->description;
869     comments = src->comments;
870     ctime = src->ctime;
871     etime = src->etime;
872     tags = src->tags;
873     is_directory = src->is_directory;
874     sorted_location = src->sorted_location;
875     store_compressed = src->store_compressed;
876     generate_csum = src->generate_csum;
877     mimetype = src->mimetype;
878     csum = src->csum;
879     compressed_csum = src->compressed_csum;
881     sfinx_id_t id;
882     sfinx_object_t mtag;
883     sfinx_size_t fsize, compressed_fsize;
884     string name, orig_name, title, authority, description, comments, mimetype, csum,
885       compressed_csum;
886     sfinx_timestamp_t ctime, etime;
887     bool is_directory, sorted_location, store_compressed, generate_csum;
888     vector <sfinx_object_t> tags;
889     sfinx_file_t(sfinx_tid_t tid = SFINX_ELEMENT_FILE) : sfinx_t(tid) { clear(); }
890     const char *sidstr() { return "File"; }
892     friend class sfinx_files_vector_t;
895 class sfinx_files_vector_t : public sfinx_t {
896   void clear() {
897     for (u32_t i = 0; i < files.size(); i++)
898       delete files[i];
899     files.clear();
900     size_ = 0;
902   sfinx_size_t size() {
903     size_ = 0;
904     for (u32_t i = 0; i < files.size(); i++)
905       size_ += files[i]->size();
906     return size_;
907  }  
908   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
909     int32_t space = available_buf_space;
910     u32_t offset = 0;
911     for (u32_t i = 0; i < files.size(); i++) {
912       int32_t sz = files[i]->put(buf + offset, available_buf_space - offset);
913       if (!sz || ((space - sz) < 0))
914         bug();
915       space -= sz;
916       offset += sz;
917    }
918     return offset;
920   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
921     int32_t space = object_size_in_buf;
922     int32_t offset = 0;
923     clear();
924     while (space) {
925       sfinx_file_t *file = new sfinx_file_t;
926       int32_t sz = file->get(buf + offset, object_size_in_buf - offset);
927       if (!sz)
928         bug();
929       offset += sz;
930       if ((space - sz) < 0)
931         bug();
932       files.push_back(file);
933       size_ += file->size();
934       space -= sz;
935    }
936     return offset;
938   public:
939   void copy(const sfinx_t *s) {
940     const sfinx_files_vector_t *src = dynamic_cast<const sfinx_files_vector_t *>(s);
941     if (!src)
942       bug();
943     clear();
944     copy_size_tid(s);
945     for (u32_t i = 0; i < src->files.size(); i++)
946       if (!add(src->files[i]))
947         bug();
949     vector <sfinx_file_t *> files;
950     sfinx_files_vector_t(sfinx_tid_t tid = SFINX_ELEMENT_FILE_VECTOR) : sfinx_t(tid) { clear(); }
951     ~sfinx_files_vector_t() { clear(); }
952     bool add(sfinx_file_t &f) { return add(&f); }
953     bool add(sfinx_file_t *f) {
954       sfinx_file_t *nf = new sfinx_file_t;
955       nf->copy(f);
956       files.push_back(nf);
957       size_ += nf->size();
958       return true;
959    }
963 class sfinx_note_t : public sfinx_t {
964   sfinx_size_t size() {
965     // count tags size
966     u32_t tags_size = sizeof(u32_t);
967     for (u32_t i = 0; i < tags.size(); i++)
968       tags_size += tags[i].size();    
969     return (size_ = tags_size + sizeof(sfinx_id_t) + mtag.size() + name.size() + 1 +
970       url.size() + 1 + text.size() + 1 + sizeof(u8_t) + ctime.size() + etime.size());
972   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
973     if (size() > available_buf_space)
974       return 0;
975     buf += ::put(id, buf);
976     buf += mtag.put(buf);
977     buf += ::put(name, buf);
978     buf += ::put(url, buf);
979     buf += ::put(text, buf);
980     buf += ::put(secured, buf);
981     buf += ctime.put(buf);
982     buf += etime.put(buf);
983     u32_t x = tags.size();
984     buf += ::put(x, buf);
985     for (u32_t i = 0; i < x; i++)
986       buf += tags[i].put(buf);
987     return size_;
989   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
990     u8_t *tmp = buf;
991     buf += ::get(&id, buf);
992     buf += mtag.get(buf);
993     buf += ::get(&name, buf);
994     buf += ::get(&url, buf);
995     buf += ::get(&text, buf);
996     buf += ::get(&secured, buf);
997     buf += ctime.get(buf);
998     buf += etime.get(buf);
999     u32_t x;
1000     buf += ::get(&x, buf);
1001     for (u32_t i = 0; i < x; i++) {
1002       sfinx_object_t o;
1003       buf += o.get(buf);
1004       tags.push_back(o);
1005    }
1006     if (size() != (sfinx_size_t)(buf - tmp))
1007       bug();
1008     return size_;
1010   public:
1011   void copy(const sfinx_t *s) {
1012     const sfinx_note_t *src = dynamic_cast<const sfinx_note_t *>(s);
1013     if (!src)
1014       bug();
1015     ((sfinx_t *)s)->size();
1016     copy_size_tid(src);
1017     id = src->id;
1018     mtag = src->mtag;
1019     name = src->name;
1020     url = src->url;
1021     text = src->text;
1022     secured = src->secured;
1023     ctime = src->ctime;
1024     etime = src->etime;
1025     tags = src->tags;
1027     sfinx_id_t id;
1028     string name, url, text;
1029     u8_t secured; // 0 - none, 1 - crypted text, 2 - crypted text + url, 3 - all crypted
1030     sfinx_timestamp_t ctime, etime;
1031     sfinx_object_t mtag; // main tag
1032     vector <sfinx_object_t> tags;
1033     sfinx_note_t(sfinx_tid_t tid = SFINX_ELEMENT_NOTE) : sfinx_t(tid) { size(); secured = 0; }
1036 #include <math.h>
1038 class sfinx_progress_t : public sfinx_t {
1040   string label_, strval_;
1041   u8_t status_, type_, precision_;
1042   float max_, val_, old_val;
1043   sfinx_size_t size() {
1044     return (size_ = 3 * sizeof(u8_t) + label_.size() + 1 + 2 * sizeof(float));
1046   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
1047     u8_t *tmp = buf;
1048     buf += ::get(&label_, buf);
1049     buf += ::get(&status_, buf);
1050     buf += ::get(&type_, buf);
1051     buf += ::get(&precision_, buf);
1052     buf += ::get(&max_, buf);
1053     buf += ::get(&val_, buf);
1054     if (size() != (sfinx_size_t)(buf - tmp))
1055       bug();
1056     return size_;
1058   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
1059     if (size() > available_buf_space)
1060       return 0;
1061     buf += ::put(label_, buf);
1062     buf += ::put(status_, buf);
1063     buf += ::put(type_, buf);
1064     buf += ::put(precision_, buf);
1065     buf += ::put(max_, buf);
1066     buf += ::put(val_, buf);
1067     return size_;
1069   public:
1070   void copy(const sfinx_t *s) {
1071     const sfinx_progress_t *src = dynamic_cast<const sfinx_progress_t *>(s);
1072     if (!src)
1073       bug();
1074     copy_size_tid(s);
1075     label_ = src->label_;
1076     status_ = src->status_;
1077     max_ = src->max_;
1078     val_ = src->val_;
1079     type_ = src->type_;
1080     precision_ = src->precision_;
1082   sfinx_progress_t(sfinx_tid_t tid = SFINX_ELEMENT_PROGRESS) : sfinx_t(tid) {
1083       val_ = max_ = old_val = 0;
1084       type_ = SFINX_PROGRESS_PERCENT;
1085       precision_ = 1;
1086       status_ = SFINX_PROGRESS_NONE;
1087       size();
1088    }
1089     void precision(char p) { precision_ = p; }
1090     void type(char t) { type_ = t; }
1091     sfinx_progress_t(const char *l) : sfinx_t(SFINX_ELEMENT_PROGRESS) {
1092       label_ = l;
1093       val_ = max_ = old_val = 0;
1094       type_ = SFINX_PROGRESS_PERCENT;
1095       precision_ = 1;
1096       status_ = SFINX_PROGRESS_START;
1097       size();
1098    }
1099     void max(float m) { max_ = m; status_ = SFINX_PROGRESS_START; }
1100     float max() { return max_; }
1101     float value() { return val_; }
1102     const char *strvalue() {
1103       char buf[128];
1104       switch(type_) {
1105         case SFINX_PROGRESS_PERCENT:
1106           sprintf(buf, "%.*f %%", (int) precision_, (val_/max_) * 100.0);
1107           break;
1108         case SFINX_PROGRESS_INTEGER:
1109           sprintf(buf, "%d", (int) val_);
1110           break;
1111         case SFINX_PROGRESS_FLOAT:
1112           sprintf(buf, "%.*f", (int) precision_, val_);
1113           break;
1114      }
1115        strval_ = buf;
1116        return strval_.c_str();
1117    }
1118     void end() { status_ = SFINX_PROGRESS_END; };
1119     int status() { return status_; }
1120     const char *label() { return label_.c_str(); }
1121     // p - percent offset - ÅÓÌÉ ÚÎÁÞÅÎÉÅ ÉÚÍÅÎÉÌÏÓØ ÂÏÌÅÅ ÞÅÍ ÎÁ p - return true
1122     bool set(float v, float p) {
1123       bool res;
1124       if (fabsf((v - old_val)/100.0) >= p) {
1125         res = true;
1126         old_val = v;
1127       } else
1128         res = false;
1129       val_ = v;
1130       return res;
1131    }
1135 class sfinx_search_query_t : public sfinx_t {
1137   vector <u32_t> areas;
1138   u32_t sort_by;
1140   sfinx_size_t size() { return (size_ = pattern.size() + 1); }
1141   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
1142     if (size() > available_buf_space)
1143       return 0;
1144     buf += ::put(pattern, buf);
1145     return size_;
1147   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
1148     buf += ::get(&pattern, buf);
1149     return size();
1151   public:
1152   void copy(const sfinx_t *s) {
1153     const sfinx_search_query_t *q = dynamic_cast<const sfinx_search_query_t *>(s);
1154     if (!q)
1155       bug();
1156     copy_size_tid(q);
1157     pattern = q->pattern;
1158     areas = q->areas;
1160   string pattern;
1161   sfinx_search_query_t(sfinx_tid_t tid = SFINX_ELEMENT_SEARCH_QUERY) : sfinx_t(tid) { size(); }
1162   void add_area(u32_t area) { areas.push_back(area); }
1165 static sfinx_t *make_sfinx_element(sfinx_tid_t tid)
1167   switch (tid) {
1168     case SFINX_ELEMENT_8BIT:
1169     case SFINX_ACCESS_GRANTED:
1170     case SFINX_ACCESS_DENIED:
1171 //    case SFINX_SLICES_MODULE_TREE_REQUEST:
1172     case SFINX_FILES_MODULE_CONF_REQUEST:
1173       return new sfinx_8bit_t(tid);
1174     case SFINX_ELEMENT_32BIT:
1175     case SFINX_DELETE_SLICE_WITH_REATTACH:
1176     case SFINX_DELETE_SLICE_ASSOC_DATA:
1177     case SFINX_DELETE_SLICE_ASSOC_DATA_RECURSIVLY:
1178     case SFINX_DELETE_SLICE_MARK_DATA_UNSORTED:
1179     case SFINX_DELETE_SLICE_MARK_DATA_UNSORTED_RECURSIVLY:
1180     case SFINX_DELETE_SLICE_RECURSIVLY:
1181     case SFINX_EDIT_SLICE_REQUEST:
1182 //    case SFINX_SLICES_MODULE_TREE_REQUEST_EXCEPT:
1183     case SFINX_OBJECTS_TREE_REQUEST:
1184       return new sfinx_32bit_t(tid);
1185     case SFINX_ELEMENT_8BIT_VECTOR:
1186     case SFINX_DAEMON_VERSION:
1187     case SFINX_PACKET_CRYPT_TYPES:
1188     case SFINX_MIN_AUTH_LEVELS:
1189     case SFINX_MD5_SUM:
1190     case SFINX_AUTH_REQUEST:
1191       return new sfinx_8bit_vector_t(tid);
1192     case SFINX_ELEMENT_SLICE:
1193     case SFINX_EDIT_SLICE:
1194     case SFINX_NEW_SLICE:  
1195     case SFINX_SLICE_RELINK:
1196 //    case SFINX_NOTES_MODULE_TREE_REQUEST:  
1197       return new sfinx_slice_t(tid);
1198     case SFINX_ELEMENT_SLICE_VECTOR:
1199 //    case SFINX_SLICES_MODULE_TREE:
1200 //    case SFINX_SLICES_MODULE_TREE_EXCEPT:
1201 //    case SFINX_NOTES_MODULE_TREE:
1202     case SFINX_OBJECTS_TREE:
1203       return new sfinx_slice_vector_t(tid);
1204     case SFINX_ELEMENT_PAIR:
1205       return new sfinx_pair_t(tid);
1206     case SFINX_ELEMENT_PAIR_VECTOR:
1207     case SFINX_FILES_MODULE_CONF:
1208       return new sfinx_pair_vector_t(tid);
1209     case SFINX_ELEMENT_STRING:
1210     case SFINX_ALERT:
1211     case SFINX_FILES_MODULE_CLASSIFY_REPLY:
1212     case SFINX_FILES_MODULE_EDIT_REPLY:
1213     case SFINX_NOTES_MODULE_ADD_REPLY:
1214     case SFINX_NOTES_MODULE_EDIT_REPLY:
1215     case SFINX_NOTES_MODULE_UNLINK_REPLY:
1216     case SFINX_NOTES_MODULE_UNSORT_REPLY:
1217     case SFINX_FILES_MODULE_SORTED_UNLINK_REPLY:
1218     case SFINX_FILES_MODULE_UNSORT_REPLY:
1219       return new sfinx_string_t(tid);
1220     case SFINX_ELEMENT_FILE_VECTOR:
1221 //    case SFINX_FILES_MODULE_SORTED_TREE:
1222     case SFINX_FILES_MODULE_UNSORTED_TREE:
1223       return new sfinx_files_vector_t(tid);
1224     case SFINX_ELEMENT_PROGRESS:
1225       return new sfinx_progress_t(tid);
1226     case SFINX_ELEMENT_FILE:
1227     case SFINX_FILES_MODULE_CLASSIFY_REQUEST:
1228 //    case SFINX_FILES_MODULE_SORTED_TREE_REQUEST:
1229     case SFINX_FILES_MODULE_UNSORTED_TREE_REQUEST:
1230     case SFINX_FILES_MODULE_EDIT_REQUEST:
1231     case SFINX_FILES_MODULE_EDIT_FILE:
1232     case SFINX_FILES_MODULE_SORTED_UNLINK:
1233     case SFINX_FILES_MODULE_UNSORT:
1234     case SFINX_FILES_MODULE_UNSORTED_DELETE:
1235       return new sfinx_file_t(tid);
1236     case SFINX_ELEMENT_SEARCH_QUERY:
1237       return new sfinx_search_query_t(tid);
1238     case SFINX_ELEMENT_SEARCH_RESULT:
1239       return new sfinx_pair_vector_t(tid);
1240     case SFINX_NOTES_MODULE_ADD:
1241     case SFINX_NOTES_MODULE_EDIT_REQUEST:
1242     case SFINX_NOTES_MODULE_EDIT:
1243     case SFINX_NOTES_MODULE_UNLINK:
1244     case SFINX_NOTES_MODULE_UNSORT:
1245       return new sfinx_note_t(tid);
1246     default:
1247       debug("Unknown element %s (id 0x%x)", sfinx_cmd2str(tid), tid);
1249   return 0;
1252 //sfinx_32bit_vector_t
1253 //sfinx_64bit_t
1254 //sfinx_64bit_vector_t
1255 //sfinx_float_t
1256 //sfinx_float_vector_t
1257 //sfinx_double_t
1258 //sfinx_double_vector_t
1259 //sfinx_string_vector_t
1260 //sfinx_date_t
1261 //sfinx_date_vector_t
1262 //sfinx_blob_t
1264 // TODO: - support for 64 bit lengths/values
1266 // ÎÅËÉÊ ÂÕÆÅÒ ÉÚ sfinx ÜÌÅÍÅÎÔÏ×
1267 class sfinx_elements {
1269   sfinx_size_t data_offset_, allocated_size_;
1270   u8_t *buf_;
1271   u32_t n_elements, current_element;
1272   // tree
1273   vector <sfinx_t *> elements;
1274   // u32_t curr_offset;
1276   public:
1277     u32_t count(sfinx_tid_t tid) {
1278       u32_t count_ = 0;
1279       for (u32_t i = 0; i < elements.size(); i++) {
1280         if (elements[i]->tid() == tid)
1281           count_++;
1282     }
1283       return count_;
1284    }
1285     sfinx_t *next() {
1286       if (current_element == elements.size())
1287         return 0;
1288       else
1289         return elements[current_element++];
1290    }
1291     sfinx_t *get(sfinx_tid_t el_id, u32_t el_offset = 0) {
1292       for (u32_t i = 0; i < elements.size(); i++) {
1293         // curr_offset = i;
1294         if (elements[i]->tid() == el_id) {
1295           if (!el_offset)
1296             return elements[i];
1297           else
1298             el_offset--;
1299        }
1300      }
1301       return 0;
1302    }
1303     // parse elements from binary buffer
1304     bool parse(u8_t *buf, u32_t buf_len) {
1305       u32_t current_position = 0;
1306       current_element = 0;
1307       s32_t buf_len_ = buf_len;
1308       while (buf_len_) {
1309         // id
1310         u32_t id_be32 = 0;
1311         u8_t first_byte = buf[current_position]; // id byte
1312         u8_t id_len = decoded_size(first_byte);
1313         memcpy(((u8_t *)&id_be32) + (sizeof(u32_t) - id_len), buf + current_position, id_len);
1314         sfinx_tid_t id = decode(id_be32, id_len);
1315         current_position += id_len;
1316         // len
1317         u32_t len_be32 = 0;
1318         first_byte = buf[current_position]; // len byte
1319         u8_t len_size = decoded_size(first_byte);
1320         memcpy(((u8_t *)&len_be32) + (sizeof(u32_t) - len_size), buf + current_position, len_size);
1321         u32_t len = decode(len_be32, len_size);
1322         current_position += len_size;
1323         buf_len_ -= (id_len + len_size + len);
1324         debug("got object %s,  id_len - %d, len_size - %d, object len - %d, buf_len - %d",
1325           sfinx_cmd2str(id), id_len, len_size, len, buf_len);
1326         if (!len)
1327           debug("Obj %s has zero len",  sfinx_cmd2str(id));
1328         if (buf_len_ < 0) {
1329           debug("Too small buf len");
1330           return 1;
1331        } else {
1332           sfinx_t *el;
1333           // allocate element
1334           el = make_sfinx_element(id);
1335           if (!el)
1336             return 1;
1337           if (len) {
1338             sfinx_size_t copied = el->get(buf + current_position, len);
1339             if (copied != len) {
1340               debug("%s parsing error, copied %lld from %d !",  sfinx_cmd2str(id), copied, len);
1341               delete el;
1342               return 1;
1343            }
1344          }
1345           elements.push_back(el);
1346           debug("parsed ok: object: %s, len - %d", sfinx_cmd2str(id), len);
1347         } // else buf_len is ok
1348         // data
1349         current_position += len;
1350      } // while
1351       return 0;
1352    }
1353     sfinx_elements() { buf_ = 0; clear(); }
1354     ~sfinx_elements() { clear(); }
1355     static s8_t decoded_size(u8_t first_byte) {
1356       u8_t mask = 0x80;
1357       for (s8_t size = 0; size < 4; size++) {
1358         if (first_byte & (mask >> size))
1359           return (size + 1);
1360      }
1361       return -1;
1362    }
1363     static s8_t coded_size(u32_t val) {
1364       if (val < 0x7F) // 2^7 - 1
1365         return 1;
1366       else if (val < 0x3FFFL) // 2^14 - 1
1367         return 2;
1368       else if (val < 0x1FFFFFL) // 2^21 - 1
1369         return 3;
1370       else if (val < 0x0FFFFFFFL) // 2^28 - 1
1371         return 4;
1372       else
1373         return -1;
1374    }
1375     // code value in utf8-like manner
1376     // returns be32 value
1377     static u32_t code(u32_t val, s8_t *coded_size_ = 0) {
1378       s8_t _coded_size_ = coded_size(val);
1379       if (_coded_size_ < 1)
1380         return 0;
1381       u8_t msb = (val >> ((_coded_size_ - 1) * 8)) & 0xFF;
1382       // code msb
1383       msb &= (0xFF >> (_coded_size_ - 1));
1384       msb |= (0x80 >> (_coded_size_ - 1));
1385       val &= ~(0xFFL << ((_coded_size_ - 1) * 8));
1386       val |= (msb << ((_coded_size_ - 1) * 8));
1387       if (coded_size_)
1388         *coded_size_ = _coded_size_;
1389       return htonl(val);
1390    }
1391     static u32_t decode(u32_t val_be32, s8_t decode_size) {
1392       val_be32 &= ~((0x80000000L >> (8 * (decode_size - 1))) >> (decode_size - 1));
1393       return ntohl(val_be32);
1394    }
1395     void clear() {
1396       data_offset_ = allocated_size_ = 0;
1397       if (buf_)
1398         delete [] buf_;
1399       buf_ = 0;
1400       n_elements = 0;
1401       for (u32_t i = 0; i < elements.size(); i++)
1402         delete elements[i];
1403       elements.clear();
1404       current_element = 0;
1405    }
1406     int add(sfinx_t &el) { return add(&el); }
1407     int add(sfinx_t *element) {
1408       s8_t element_id_size = -1, element_length_size = -1;
1409       u32_t coded_id_be32 = code(element->tid(), &element_id_size),
1410         coded_element_length_be32 = code(element->size(), &element_length_size);
1411       if ((element_id_size < 0) || (element_length_size < 0))
1412         return -1;
1413       sfinx_size_t space = element->size() + data_offset_ + element_id_size + element_length_size;
1414       if (space > allocated_size_) {
1415             space *= 1.2;
1416             u8_t *buf = new u8_t[space];
1417             if (allocated_size_) {
1418               memcpy(buf, buf_, allocated_size_);
1419               delete [] buf_;
1420            }
1421             allocated_size_ = space;
1422             buf_ = buf;
1423      }
1424       // add element id
1425       memcpy(buf_ + data_offset_, ((u8_t *)&coded_id_be32) + (sizeof(u32_t) - element_id_size),
1426         element_id_size);
1427       data_offset_ += element_id_size;
1428       // add element length
1429       memcpy(buf_ + data_offset_, ((u8_t *)&coded_element_length_be32) + (sizeof(u32_t) -
1430         element_length_size), element_length_size);
1431       data_offset_ += element_length_size;
1432       // add element data
1433       sfinx_size_t res = element->put(buf_ + data_offset_, allocated_size_ - data_offset_);
1434       if (res != element->size()) {
1435         debug("%s data copy error: buf_size - %lld, el_size - %lld, copied - %lld",
1436           sfinx_cmd2str(element->tid()), allocated_size_ - data_offset_, element->size(), res);
1437         return -3;
1438      }
1439       data_offset_ += element->size();
1440        debug("sending %s, el_id_size - %d, el_len - %lld (be_len 0x%x), el_len_size - %d, "
1441          "copied - %lld, data_size in tx_buf - %lld", sfinx_cmd2str(element->tid()),
1442          element_id_size, element->size(), coded_element_length_be32, element_length_size,
1443          res, data_offset_);
1444       n_elements++;
1445       return 0;
1446    }
1447     sfinx_size_t size() { return data_offset_; }
1448     u8_t *buf() { return buf_; }
1451 #endif