.
[sfinx.git] / include / elements.H
blobbfc25dfbd7780d4d4662f915cc36daf5f647a55f
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     // ËÏÎÓÔÒÕËÔÏÒ ËÏÐÉÒÏ×ÁÎÉÑ ÐÏÄÈÏÄÉÔ ÐÏ ÕÍÏÌÞÁÎÉÀ
194     sfinx_timestamp_t() : Timestamp() { mDate = IBPP::MinDate; mTime = 0; }
195     sfinx_timestamp_t(const Timestamp &t) : Timestamp(t) { }
196     sfinx_size_t size() { return (sizeof(mDate) + sizeof(mTime)); }
197     sfinx_size_t get(u8_t *buf) {
198       u32_t date, time;
199       memcpy(&date, buf, sizeof(date));
200       memcpy(&time, buf + sizeof(date), sizeof(time));
201       SetDate(date);
202       SetTime(time);
203       return size();
204    }
205     sfinx_size_t put(u8_t *buf) {
206       u32_t date, time;
207       date = GetDate();
208       time = GetTime();
209       memcpy(buf, &date, sizeof(date));
210       memcpy(buf + sizeof(date), &time, sizeof(time));
211       return size();
212    }
213     void set(time_t t) {
214       tm *loctime = localtime(&t);
215       if (!IBPP::itod(&mDate, loctime->tm_year + 1900, loctime->tm_mon + 1, loctime->tm_mday))
216         log("sfinx_timestamp_t", "Out of range");
217       IBPP::itot(&mTime, loctime->tm_hour, loctime->tm_min, loctime->tm_sec, 0);
218    }
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, main_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 m) {
241       type = t;
242       id = i;
243       main_slice_id = m;
244    }
245     sfinx_object_t(sfinx_type_t t, sfinx_id_t i, sfinx_id_t m, const char *n, sfinx_timestamp_t &ct,
246       sfinx_timestamp_t &et) {
247         type = t;
248         id = i;
249         main_slice_id = m;
250         name = n;
251         ctime = ct;
252         etime = et;
253    }
254     sfinx_size_t size() { return (2 * sizeof(sfinx_id_t) + sizeof(sfinx_type_t) + name.size() + 1 +
255       path_name.size() + 1 + description.size() + 1 + ctime.size() + etime.size()); }
256     sfinx_size_t get(u8_t *buf) {
257       u8_t *t = buf;
258       buf += ::get(&id, buf);
259       buf += ::get(&main_slice_id, buf);
260       buf += ::get(&type, buf);
261       buf += ::get(&name, buf);
262       buf += ::get(&path_name, buf);
263       buf += ::get(&description, buf);
264       buf += ctime.get(buf);
265       buf += etime.get(buf);
266       return (buf - t);
267    }
268     u32_t put(u8_t *buf) {
269       u8_t *t = buf;
270       buf += ::put(id, buf);
271       buf += ::put(main_slice_id, buf);
272       buf += ::put(type, buf);
273       buf += ::put(name, buf);
274       buf += ::put(path_name, buf);
275       buf += ::put(description, buf);
276       buf += ctime.put(buf);
277       buf += etime.put(buf);      
278       return (buf - t);
279    }
282 class sfinx_slice_t : public sfinx_t {
284   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
285     if (available_buf_space < size())
286       return 0;
287     u8_t *t = buf;
288     buf += ::put(id, buf);
289     buf += ::put(parent_id, buf);
290     buf += ::put(name_, buf);
291     buf += ::put(directory_, buf);
292     buf += ::put(description_, buf);
293     buf += ::put(parent_name_, buf);
294     buf += ctime.put(buf);
295     buf += etime.put(buf);
296     // objs
297     u32_t l = objs.size();
298     buf += ::put(l, buf);
299     for (u32_t i = 0; i < l; i++)
300       buf += objs[i].put(buf);
301     return (buf - t);
303   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
304     u8_t *t = buf;
305     buf += ::get(&id, buf);
306     buf += ::get(&parent_id, buf);
307     buf += ::get(&name_, buf);
308     buf += ::get(&directory_, buf);
309     buf += ::get(&description_, buf);
310     buf += ::get(&parent_name_, buf);
311     buf += ctime.get(buf);
312     buf += etime.get(buf);
313     // objs
314     u32_t l;
315     buf += ::get(&l, buf);
316     for (u32_t i = 0; i < l; i++) {
317       sfinx_object_t obj;
318       buf += obj.get(buf);
319       objs.push_back(obj);
320    }
321    // hmm, ÐÒÏ×ÅÒËÁ ÌÉÛØ × ËÏÎÃÅ
322     if ((sfinx_size_t)(buf - t) > object_size_in_buf)
323       return 0;
324     return size();
327   public:
329   void copy(const sfinx_t *s) {
330       if (!dynamic_cast<const sfinx_slice_t *>(s))
331         bug();
332       copy_size_tid(s);
333       const sfinx_slice_t *s_ = (const sfinx_slice_t *)s;
334       id = s_->id;
335       name_ = s_->name_;
336       directory_ = s_->directory_;
337       parent_name_ = s_->parent_name_;
338       description_ = s_->description_;
339       parent_id = s_->parent_id;
340       ctime = s_->ctime;
341       etime = s_->etime;
342       objs = s_->objs;
344   sfinx_id_t id;
345   string name_, directory_, description_, parent_name_;
346   sfinx_id_t parent_id;
347   sfinx_timestamp_t ctime, etime;
348   vector <sfinx_object_t> objs; // ×ÌÏÖÅÎÎÙÅ × ÓÌÁÊÓ ÏÂØÅËÔÙ
350   const char *name() { return name_.c_str(); }
351   const char *directory() { return directory_.c_str(); }
352   const char *description() { return description_.c_str(); }
353   const char *parent_name() { return parent_name_.c_str(); }
355   void add(sfinx_object_t &obj) { objs.push_back(obj); }
356   void name(const char *s) { name_ = s; size(); }
357   void directory(const char *d) { directory_ = d; size(); }
358   void description(const char *s) { description_ = s; size(); }
359   void parent_name(const char *s) { parent_name_ = s; size(); }
361   sfinx_slice_t(sfinx_tid_t tid = SFINX_ELEMENT_SLICE) : sfinx_t(tid) {
362     parent_id = id = 0;
363     size();
365   sfinx_slice_t(sfinx_slice_t *s) : sfinx_t(SFINX_ELEMENT_SLICE) { copy(s); }
366   sfinx_slice_t(sfinx_id_t id_, string &name__, string &directory__, string &description__,
367     string &parent_name__, sfinx_id_t parent_id, sfinx_timestamp_t ctime_, sfinx_timestamp_t etime_,
368       sfinx_tid_t tid = SFINX_ELEMENT_SLICE) : sfinx_t(tid), id(id_), name_(name__),
369       directory_(directory__), description_(description__), parent_name_(parent_name__),
370       parent_id(parent_id), ctime(ctime_), etime(etime_) { size(); }
371   sfinx_size_t size() {
372      u32_t s = sizeof(u32_t); // ÄÌÉÎÁ ÓÞÅÔÞÉËÁ ÏÂØÅËÔÏ×
373      for (u32_t i = 0; i < objs.size(); i++)
374        s += objs[i].size();
375      return (size_ = sizeof(id) + name_.size() + 1 + directory_.size() + 1 +
376        description_.size() + 1 + parent_name_.size() + 1 + sizeof(parent_id) + ctime.size() +
377        etime.size() + s);
379   friend class sfinx_slice_vector_t;
382 class sfinx_slice_vector_t : public sfinx_t {
384   vector <sfinx_slice_t *> slices;  
386   sfinx_size_t size() {
387     size_ = 0;
388     for (u32_t i = 0; i < slices.size(); i++)
389       size_ += slices[i]->size();
390     return size_;
392   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
393     u32_t offset = 0;
394     for (u32_t i = 0; i < slices.size(); i++) {
395       if (slices[i]->put(buf + offset, available_buf_space) != slices[i]->size())
396         return 0;
397       available_buf_space -= slices[i]->size();
398       offset += slices[i]->size();
399    }
400     return size();
402   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
403     clear();
404     while (object_size_in_buf) {
405       sfinx_slice_t *slice = new sfinx_slice_t;
406       sfinx_size_t res = slice->get(buf + size(), object_size_in_buf);
407       if (res != slice->size()) {
408         delete slice;
409         return 0;
410      }
411       add(slice);
412       if (object_size_in_buf < slice->size())
413         return 0;
414       object_size_in_buf -= slice->size();
415    }
416     return size();
418   void clear() {
419     for (u32_t i = 0; i < slices.size(); i++)
420       delete slices[i];
421     slices.clear();
422     size_ = 0;
424   public:
425   void copy(const sfinx_t *s) {
426     const sfinx_slice_vector_t *src = dynamic_cast<const sfinx_slice_vector_t *>(s);
427     if (!src)
428       bug();
429     clear();
430     copy_size_tid(src);
431     for (u32_t i = 0; i < src->slices.size(); i++) {
432       sfinx_slice_t *slice = new sfinx_slice_t(src->slices[i]);
433       slices.push_back(slice);
434    }
436     sfinx_slice_vector_t(sfinx_tid_t tid = SFINX_ELEMENT_SLICE_VECTOR) : sfinx_t(tid) { }
437     ~sfinx_slice_vector_t() { clear(); }
438     void add(sfinx_slice_t *slice) {
439       sfinx_slice_t *s = new sfinx_slice_t(slice);
440       slices.push_back(s); // ËÏÐÉÒÕÅÍ ÏÂØÅËÔ
441       size_ += slice->size();
442    }
443     void add(sfinx_slice_t &slice) { add(&slice); }
444     u32_t len() { return slices.size(); }
445     sfinx_slice_t *get(u32_t idx) { return slices[idx]; }
446     sfinx_slice_t *find(u32_t id) {
447       for (u32_t i = 0; i < slices.size(); i++) {
448         if (id == slices[i]->id)
449           return slices[i];
450      }
451       return 0;
452    }
455 class sfinx_string_t : public sfinx_t {
456   string s;
457   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
458     if (available_buf_space < (s.size() + 1))
459       return 0;
460     if (!s.size())
461       buf[0] = 0;
462     else
463       strcpy((char *)buf, s.c_str());
464     return size();
466   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
467     s = (char *) buf;
468     return size();
470   public:
471   void copy(const sfinx_t *s_) {
472     if (!dynamic_cast<const sfinx_string_t *>(s_))
473       bug();
474     copy_size_tid(s_);
475     s = ((const sfinx_string_t *)s_)->s;
477     sfinx_size_t size() { return (size_ = s.size() + 1); }
478     sfinx_string_t(sfinx_tid_t tid = SFINX_ELEMENT_STRING) : sfinx_t(tid) { size_ = 1; }
479     sfinx_string_t(const char *s_) : sfinx_t(SFINX_ELEMENT_STRING) {
480       s = s_;
481       size();
482    }
483     const char *c_str() { return s.c_str(); }
484     bool get(string &s_) { s_ = s; return true; }
485     bool set(string &s_) {
486       if (s_.size())
487         s = s_;
488       else
489          s.clear();
490       size();
491       return true;
492    }
493     bool set(const char *s_) {
494       if (s_)
495         s = s_;
496       else
497         s.clear();
498       size();
499       return true;
500    }
503 // ÐÁÒÁ ÅÌÅÍÅÎÔÏ× int -> sfinx_t
504 class sfinx_pair_t : public sfinx_t {
505     u32_t key_;
506     sfinx_t *element;
507   void clear() {
508     key_ = SFINX_KEY_UNASSIGNED;
509     if (element)
510       delete element;
511     element = 0;
512     size_ = 0;
514   sfinx_size_t size() { return (size_ = element->size() + 2 * sizeof(u32_t)); } // + element id
515   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
516     if (available_buf_space < size())
517       return 0;
518     buf += ::put(key_, buf);
519     sfinx_tid_t eid = element->tid();
520     buf += ::put(eid, buf);
521     //debug("eid - %x, size - %d, space - %d", eid, size(), available_buf_space);
522     if (!element->put(buf, available_buf_space - (sizeof(eid) + sizeof(key_))))
523       return 0;
524     return size();
526   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
527     clear();
528     buf += ::get(&key_, buf);
529     sfinx_tid_t eid;
530     buf += ::get(&eid, buf);
531     //debug("eid - %x, size_in_buf - %d", eid, object_size_in_buf);
532     if (!eid)
533       bug();
534     element = make_sfinx_element(eid);
535     if (element) {
536       element->get(buf, object_size_in_buf -  (sizeof(eid) + sizeof(key_)));
537       return size();
538    }
539     return 0;
541   public:
542   void copy(const sfinx_t *s) {
543     const sfinx_pair_t *src = dynamic_cast<const sfinx_pair_t *>(s);
544     if (!src)
545       bug();
546     clear();
547     copy_size_tid(src);
548     element = make_sfinx_element(src->element->tid());
549     if (!element)
550       bug();
551     element->copy(src->element);
552     key_ = src->key_;
554     sfinx_pair_t(sfinx_tid_t tid = SFINX_ELEMENT_PAIR) : sfinx_t(tid) {
555       key_ = SFINX_KEY_UNASSIGNED; element = 0;
556    }
557     u32_t key() { return key_; }
558     ~sfinx_pair_t() { clear(); }
559     bool get(u32_t k, uint32_t *v) {
560       if (k != key_)
561         return false;
562       return element->get(v);
563    }
564     bool get(u32_t k, string &s) {
565       if (k != key_)
566         return false;
567       return element->get(s);
568    }
569     bool get(u32_t k, sfinx_t **el) {
570       if (k != key_)
571         return false;
572       *el = element;
573       return true;
574    }
575     bool set(u32_t k, sfinx_t &e) { return set(k, &e); }
576     bool set(u32_t k, sfinx_t *e) {
577       // ÎÅÐÌÏÈÏ ÂÙ ÐÒÏ×ÅÒÉÔØ ÞÔÏ id() != SFINX_ELEMENT_PAIR
578       clear();
579       element = make_sfinx_element(e->tid()); // ÆÁÂÒÉËÁ ÐÕÓÔÙÈ ÅÌÅÍÅÎÔÏ× ÏÐÒ. ÔÉÐÁ
580       if (element) {
581         element->copy(e); // ÔÉÐÁ ËÏÎÔÓÒÕËÔÏÒ ËÏÐÉÒÏ×ÁÎÉÑ
582         key_ = k;
583         size();
584         return 0;
585      }
586        return 1;
587    }
588     bool set(u32_t k, string &s) {
589       clear();
590       element = new sfinx_string_t;
591       if (element) {
592         key_ = k;
593         if (!element->set(s))
594           return false;
595         size();
596         return true;
597      }
598       return false;
599    }
600     bool set(u32_t k, const char *s) { string t(s); return set(k, t); }
601     bool set(u32_t k, u32_t v) {
602       clear();
603       element = new sfinx_32bit_t;
604       element->set(v);
605       key_ = k;
606       size();
607       return true;
608   }
609    friend class sfinx_pair_vector_t;
612 // ÎÁÂÏÒ ÐÁÒ ÅÌÅÍÅÎÔÏ× int -> sfinx_t
613 class sfinx_pair_vector_t : public sfinx_t {
614   vector <sfinx_pair_t *> pairs;
615   sfinx_size_t size() {
616     size_ = 0;
617     for (u32_t i = 0; i < pairs.size(); i++)
618       size_ += pairs[i]->size();
619     return size_;
621   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
622     int32_t space = available_buf_space;
623     u32_t offset = 0;
624     for (u32_t i = 0; i < pairs.size(); i++) {
625       u32_t sz = pairs[i]->put(buf + offset, available_buf_space - offset);
626       if (!sz || ((space - sz) < 0))
627         bug();
628       space -= sz;
629       offset += sz;
630    }
631     return offset;
633   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
634     int32_t space = object_size_in_buf;
635     int32_t offset = 0;
636     clear();
637     while (space) {
638       sfinx_pair_t *pair = new sfinx_pair_t; // id ÔÅÒÑÅÍ
639       int32_t sz = pair->get(buf + offset, object_size_in_buf - offset);
640       offset += sz;
641       if (!sz || (space - sz) < 0)
642         bug();
643       pairs.push_back(pair);
644       size_ += pair->size();
645       space -= sz;
646       //debug("offset - %d, all_size - %d, space - %d", offset, object_size_in_buf, space);
647    }
648     return offset;
650   public:
651   void clear() {
652     for (u32_t i = 0; i < pairs.size(); i++)
653       delete pairs[i];
654     pairs.clear();
655     size_ = 0;
657   void copy(const sfinx_t *s) {
658     const sfinx_pair_vector_t *src = dynamic_cast<const sfinx_pair_vector_t *>(s);
659     if (!src)
660       bug();
661     clear();
662     copy_size_tid(src);
663     for (u32_t i = 0; i < src->pairs.size(); i++)
664       if (!add(src->pairs[i]))
665         bug();
667     sfinx_pair_t *find(u32_t k) {
668       for (u32_t i = 0; i < pairs.size(); i++) {
669         if (k == pairs[i]->key())
670           return pairs[i];
671      }
672       return 0;
674   u32_t len() { return pairs.size(); }
675   bool find(u32_t k, u32_t *idx) {
676     for (u32_t i = 0; i < pairs.size(); i++) {
677       if (k == pairs[i]->key()) {
678         *idx = i;
679         return 1;
680      }
681    }
682     return 0;
684   sfinx_pair_vector_t(sfinx_tid_t tid = SFINX_ELEMENT_PAIR_VECTOR) : sfinx_t(tid) { }
685   bool add(sfinx_pair_t *p) {
686     if (find(p->key()))
687       return false;
688     sfinx_pair_t *pair = new sfinx_pair_t(p->tid());
689     pair->copy(p);
690     pairs.push_back(pair);
691     size_ += pair->size();
692     return true;
694   // returns false on error (key exists)
695   bool add(u32_t k, sfinx_t *e) {
696     if (find(k))
697       return false;
698     sfinx_pair_t *p = new sfinx_pair_t;
699     if (p->set(k, e)) {
700       delete p;
701       return false;
702     } else {
703       pairs.push_back(p);
704       size_ += p->size();
705       return true;
706     }
708   // return false if key not found
709   bool get(u32_t k, uint32_t *v) {
710    sfinx_pair_t *pair = find(k);
711    if (!pair)
712      return false;
713    return pair->get(k, v);
715   bool get(u32_t k, string &s) {
716    sfinx_pair_t *pair = find(k);
717    if (!pair)
718      return false;
719    return pair->get(k, s);      
722 //    bool get(u32_t k, sfinx_t *s) {
723 //    sfinx_pair_t *pair = find(k);
724 //     if (!pair)
725 //       return false;
726 //     return pair->get(k, s);
727 //   }
729   bool add(u32_t k, uint32_t v) {
730     if (find(k))
731       return false;
732     sfinx_pair_t *pair = new sfinx_pair_t;
733     pair->set(k, v);
734     add(pair);
735     return true;
737   bool add(u32_t k, string &s) {
738     if (find(k))
739       return false;
740     sfinx_pair_t *pair = new sfinx_pair_t;
741     pair->set(k, s);
742     add(pair);
743     return true;
745   bool add(u32_t k, const char *s) { string t(s); return add(k, t); }
748 class sfinx_file_t : public sfinx_t {
749   sfinx_size_t size() {
750       u32_t objs_size = sizeof(u32_t); // obj counter
751       for (u32_t i = 0; i < objects.size(); i++)
752         objs_size += objects[i].size();
753       return (size_ = 4 * sizeof(sfinx_id_t) + 2 * sizeof(sfinx_size_t) + objs_size +
754         name.size() + 1 + orig_name.size() + 1 + title.size() + 1 + authority.size() + 1 +
755         description.size() + 1 + comments.size() + 1 + ctime.size() + etime.size() +
756         4 * sizeof(u8_t) + mimetype.size() + 1 + csum.size() + 1 + compressed_csum.size() + 1);
758   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
759     if (size() > available_buf_space)
760       return 0;
761     buf += ::put(file_id, buf);
762     u8_t v = is_directory;
763     buf += ::put(v, buf);
764     v = sorted_location;
765     buf += ::put(v, buf);
766     v = store_compressed;
767     buf += ::put(v, buf);
768     v = generate_csum;
769     buf += ::put(v, buf);
770     buf += ::put(main_obj_id, buf);
771     buf += ::put(main_obj_type, buf);
772     buf += ::put(main_slice_id, buf);
773     buf += ::put(fsize, buf);
774     buf += ::put(compressed_fsize, buf);
775     u32_t t = objects.size();
776     buf += ::put(t, buf);
777     for (u32_t i = 0; i < objects.size(); i++)
778       buf += objects[i].put(buf);
779     buf += ::put(name, buf);
780     buf += ::put(orig_name, buf);
781     buf += ::put(title, buf);
782     buf += ::put(authority, buf);
783     buf += ::put(description, buf);
784     buf += ::put(comments, buf);
785     buf += ::put(mimetype, buf);
786     buf += ::put(csum, buf);
787     buf += ::put(compressed_csum, buf);
788     buf += ctime.put(buf);
789     buf += etime.put(buf);
790     return size_;
792   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
793     u8_t *tmp = buf;
794     clear();
795     buf += ::get(&file_id, buf);
796     u8_t v;
797     buf += ::get(&v, buf);
798     is_directory = v;
799     buf += ::get(&v, buf);
800     sorted_location = v;
801     buf += ::get(&v, buf);
802     store_compressed = v;
803     buf += ::get(&v, buf);
804     generate_csum = v;
805     buf += ::get(&main_obj_id, buf);
806     buf += ::get(&main_obj_type, buf);
807     buf += ::get(&main_slice_id, buf);
808     buf += ::get(&fsize, buf);
809     buf += ::get(&compressed_fsize, buf);
810     u32_t objects_size;
811     buf += ::get(&objects_size, buf);
812     for (u32_t i = 0; i < objects_size; i++) {
813       sfinx_object_t o;
814       buf += o.get(buf);
815       objects.push_back(o);
816    }
817     buf += ::get(&name, buf);
818     buf += ::get(&orig_name, buf);
819     buf += ::get(&title, buf);
820     buf += ::get(&authority, buf);
821     buf += ::get(&description, buf);
822     buf += ::get(&comments, buf);
823     buf += ::get(&mimetype, buf);
824     buf += ::get(&csum, buf);
825     buf += ::get(&compressed_csum, buf);
826     buf += ctime.get(buf);
827     buf += etime.get(buf);
828     if (size() != (sfinx_size_t)(buf - tmp))
829       bug();
830     return size_;
832   public:
833   void clear() {
834     objects.clear();
835     file_id = main_obj_type = main_obj_id = fsize = 0;
836     is_directory = false;
837     size_ = 0;
838  }  void copy(const sfinx_t *s) {
839     const sfinx_file_t *src = dynamic_cast<const sfinx_file_t *>(s);
840     if (!src)
841       bug();
842     clear();
843     ((sfinx_t *)s)->size();
844     copy_size_tid(src);
845     file_id = src->file_id;
846     main_obj_id = src->main_obj_id;
847     main_obj_type = src->main_obj_type;
848     main_slice_id = src->main_slice_id;
849     fsize = src->fsize;
850     compressed_fsize = src->compressed_fsize;
851     name = src->name;
852     orig_name = src->orig_name;
853     title = src->title;
854     authority = src->authority;
855     description = src->description;
856     comments = src->comments;
857     ctime = src->ctime;
858     etime = src->etime;
859     objects = src->objects;
860     is_directory = src->is_directory;
861     sorted_location = src->sorted_location;
862     store_compressed = src->store_compressed;
863     generate_csum = src->generate_csum;
864     mimetype = src->mimetype;
865     csum = src->csum;
866     compressed_csum = src->compressed_csum;
868     sfinx_id_t file_id, main_obj_id, main_obj_type, main_slice_id;
869     sfinx_size_t fsize, compressed_fsize;
870     string name, orig_name, title, authority, description, comments, mimetype, csum,
871       compressed_csum;
872     sfinx_timestamp_t ctime, etime;
873     bool is_directory, sorted_location, store_compressed, generate_csum;
874     vector <sfinx_object_t> objects; // ÍÁÓÓÉ× ÔÉÐÏ× É id ÄÏÐÏÌÎÉÔÅÌØÎÙÈ ÏÂØÅËÔÏ×
875     sfinx_file_t(sfinx_tid_t tid = SFINX_ELEMENT_FILE) : sfinx_t(tid) { clear(); }
876     const char *sidstr() { return "File"; }
878     friend class sfinx_files_vector_t;
881 class sfinx_files_vector_t : public sfinx_t {
882   void clear() {
883     for (u32_t i = 0; i < files.size(); i++)
884       delete files[i];
885     files.clear();
886     size_ = 0;
888   sfinx_size_t size() {
889     size_ = 0;
890     for (u32_t i = 0; i < files.size(); i++)
891       size_ += files[i]->size();
892     return size_;
893  }  
894   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
895     int32_t space = available_buf_space;
896     u32_t offset = 0;
897     for (u32_t i = 0; i < files.size(); i++) {
898       int32_t sz = files[i]->put(buf + offset, available_buf_space - offset);
899       if (!sz || ((space - sz) < 0))
900         bug();
901       space -= sz;
902       offset += sz;
903    }
904     return offset;
906   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
907     int32_t space = object_size_in_buf;
908     int32_t offset = 0;
909     clear();
910     while (space) {
911       sfinx_file_t *file = new sfinx_file_t;
912       int32_t sz = file->get(buf + offset, object_size_in_buf - offset);
913       if (!sz)
914         bug();
915       offset += sz;
916       if ((space - sz) < 0)
917         bug();
918       files.push_back(file);
919       size_ += file->size();
920       space -= sz;
921    }
922     return offset;
924   public:
925   void copy(const sfinx_t *s) {
926     const sfinx_files_vector_t *src = dynamic_cast<const sfinx_files_vector_t *>(s);
927     if (!src)
928       bug();
929     clear();
930     copy_size_tid(s);
931     for (u32_t i = 0; i < src->files.size(); i++)
932       if (!add(src->files[i]))
933         bug();
935     vector <sfinx_file_t *> files;
936     sfinx_files_vector_t(sfinx_tid_t tid = SFINX_ELEMENT_FILE_VECTOR) : sfinx_t(tid) { clear(); }
937     ~sfinx_files_vector_t() { clear(); }
938     bool add(sfinx_file_t &f) { return add(&f); }
939     bool add(sfinx_file_t *f) {
940       sfinx_file_t *nf = new sfinx_file_t;
941       nf->copy(f);
942       files.push_back(nf);
943       size_ += nf->size();
944       return true;
945    }
949 class sfinx_note_t : public sfinx_t {
950   sfinx_size_t size() {
951     return (size_ = sizeof(u32_t) * 4 + name.size() + 1 + url.size() + 1 + text.size() + 1 +
952       sizeof(u8_t) + ctime.size() + etime.size());
954   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
955     if (size() > available_buf_space)
956       return 0;
957     buf += ::put(id, buf);
958     buf += ::put(main_obj_id, buf);
959     buf += ::put(main_obj_type, buf);
960     buf += ::put(main_slice_id, buf);
961     buf += ::put(name, buf);
962     buf += ::put(url, buf);
963     buf += ::put(text, buf);
964     buf += ::put(secured, buf);
965     buf += ctime.put(buf);
966     buf += etime.put(buf);
967     u32_t x = tags.size();
968     buf += ::put(x, buf);
969     for (u32_t i = 0; i < x; i++)
970       buf += tags[i].put(buf);
971     return size_;
973   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
974     u8_t *tmp = buf;
975     buf += ::get(&id, buf);
976     buf += ::get(&main_obj_id, buf);
977     buf += ::get(&main_obj_type, buf);
978     buf += ::get(&main_slice_id, buf);
979     buf += ::get(&name, buf);
980     buf += ::get(&url, buf);
981     buf += ::get(&text, buf);
982     buf += ::get(&secured, buf);
983     buf += ctime.get(buf);
984     buf += etime.get(buf);
985     u32_t x;
986     buf += ::get(&x, buf);
987     for (u32_t i = 0; i < x; i++) {
988       sfinx_object_t o;
989       buf += o.get(buf);
990       tags.push_back(o);
991    }
992     if (size() != (sfinx_size_t)(buf - tmp))
993       bug();
994     return size_;
996   public:
997   void copy(const sfinx_t *s) {
998     const sfinx_note_t *src = dynamic_cast<const sfinx_note_t *>(s);
999     if (!src)
1000       bug();
1001     ((sfinx_t *)s)->size();
1002     copy_size_tid(src);
1003     id = src->id;
1004     main_obj_id = src->main_obj_id;
1005     main_obj_type = src->main_obj_type;
1006     main_slice_id = src->main_slice_id;
1007     name = src->name;
1008     url = src->url;
1009     text = src->text;
1010     secured = src->secured;
1011     ctime = src->ctime;
1012     etime = src->etime;
1013     tags = src->tags;
1015     sfinx_id_t id, main_obj_id, main_obj_type, main_slice_id;
1016     string name, url, text;
1017     u8_t secured; // 0 - none, 1 - crypted text, 2 - crypted text + url, 3 - all crypted
1018     sfinx_timestamp_t ctime, etime;
1019     vector <sfinx_object_t> tags;
1020     sfinx_note_t(sfinx_tid_t tid = SFINX_ELEMENT_NOTE) : sfinx_t(tid) { size(); }
1021 //    sfinx_note_t(sfinx_id_t id_, sfinx_id_t mobj_id, sfinx_id_t mobj_type,
1022 //      sfinx_id_t mslice_id, string n, sfinx_timestamp_t ct, sfinx_timestamp_t et) :
1023 //      sfinx_t(SFINX_ELEMENT_NOTE), id(id_), main_obj_id(mobj_id), main_obj_type(mobj_type),
1024 //      main_slice_id(mslice_id), name(n), ctime(ct), etime(et) { }
1027 #include <math.h>
1029 class sfinx_progress_t : public sfinx_t {
1031   string label_, strval_;
1032   u8_t status_, type_, precision_;
1033   float max_, val_, old_val;
1034   sfinx_size_t size() {
1035     return (size_ = 3 * sizeof(u8_t) + label_.size() + 1 + 2 * sizeof(float));
1037   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
1038     u8_t *tmp = buf;
1039     buf += ::get(&label_, buf);
1040     buf += ::get(&status_, buf);
1041     buf += ::get(&type_, buf);
1042     buf += ::get(&precision_, buf);
1043     buf += ::get(&max_, buf);
1044     buf += ::get(&val_, buf);
1045     if (size() != (sfinx_size_t)(buf - tmp))
1046       bug();
1047     return size_;
1049   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
1050     if (size() > available_buf_space)
1051       return 0;
1052     buf += ::put(label_, buf);
1053     buf += ::put(status_, buf);
1054     buf += ::put(type_, buf);
1055     buf += ::put(precision_, buf);
1056     buf += ::put(max_, buf);
1057     buf += ::put(val_, buf);
1058     return size_;
1060   public:
1061   void copy(const sfinx_t *s) {
1062     const sfinx_progress_t *src = dynamic_cast<const sfinx_progress_t *>(s);
1063     if (!src)
1064       bug();
1065     copy_size_tid(s);
1066     label_ = src->label_;
1067     status_ = src->status_;
1068     max_ = src->max_;
1069     val_ = src->val_;
1070     type_ = src->type_;
1071     precision_ = src->precision_;
1073   sfinx_progress_t(sfinx_tid_t tid = SFINX_ELEMENT_PROGRESS) : sfinx_t(tid) {
1074       val_ = max_ = old_val = 0;
1075       type_ = SFINX_PROGRESS_PERCENT;
1076       precision_ = 1;
1077       status_ = SFINX_PROGRESS_NONE;
1078       size();
1079    }
1080     void precision(char p) { precision_ = p; }
1081     void type(char t) { type_ = t; }
1082     sfinx_progress_t(const char *l) : sfinx_t(SFINX_ELEMENT_PROGRESS) {
1083       label_ = l;
1084       val_ = max_ = old_val = 0;
1085       type_ = SFINX_PROGRESS_PERCENT;
1086       precision_ = 1;
1087       status_ = SFINX_PROGRESS_START;
1088       size();
1089    }
1090     void max(float m) { max_ = m; status_ = SFINX_PROGRESS_START; }
1091     float max() { return max_; }
1092     float value() { return val_; }
1093     const char *strvalue() {
1094       char buf[128];
1095       switch(type_) {
1096         case SFINX_PROGRESS_PERCENT:
1097           sprintf(buf, "%.*f %%", (int) precision_, (val_/max_) * 100.0);
1098           break;
1099         case SFINX_PROGRESS_INTEGER:
1100           sprintf(buf, "%d", (int) val_);
1101           break;
1102         case SFINX_PROGRESS_FLOAT:
1103           sprintf(buf, "%.*f", (int) precision_, val_);
1104           break;
1105      }
1106        strval_ = buf;
1107        return strval_.c_str();
1108    }
1109     void end() { status_ = SFINX_PROGRESS_END; };
1110     int status() { return status_; }
1111     const char *label() { return label_.c_str(); }
1112     // p - percent offset - ÅÓÌÉ ÚÎÁÞÅÎÉÅ ÉÚÍÅÎÉÌÏÓØ ÂÏÌÅÅ ÞÅÍ ÎÁ p - return true
1113     bool set(float v, float p) {
1114       bool res;
1115       if (fabsf((v - old_val)/100.0) >= p) {
1116         res = true;
1117         old_val = v;
1118       } else
1119         res = false;
1120       val_ = v;
1121       return res;
1122    }
1126 class sfinx_search_query_t : public sfinx_t {
1128   vector <u32_t> areas;
1129   u32_t sort_by;
1131   sfinx_size_t size() { return (size_ = pattern.size() + 1); }
1132   sfinx_size_t put(u8_t *buf, sfinx_size_t available_buf_space) {
1133     if (size() > available_buf_space)
1134       return 0;
1135     buf += ::put(pattern, buf);
1136     return size_;
1138   sfinx_size_t get(u8_t *buf, sfinx_size_t object_size_in_buf) {
1139     buf += ::get(&pattern, buf);
1140     return size();
1142   public:
1143   void copy(const sfinx_t *s) {
1144     const sfinx_search_query_t *q = dynamic_cast<const sfinx_search_query_t *>(s);
1145     if (!q)
1146       bug();
1147     copy_size_tid(q);
1148     pattern = q->pattern;
1149     areas = q->areas;
1151   string pattern;
1152   sfinx_search_query_t(sfinx_tid_t tid = SFINX_ELEMENT_SEARCH_QUERY) : sfinx_t(tid) { size(); }
1153   void add_area(u32_t area) { areas.push_back(area); }
1156 static sfinx_t *make_sfinx_element(sfinx_tid_t tid)
1158   switch (tid) {
1159     case SFINX_ELEMENT_8BIT:
1160     case SFINX_ACCESS_GRANTED:
1161     case SFINX_ACCESS_DENIED:
1162     case SFINX_SLICES_MODULE_TREE_REQUEST:
1163     case SFINX_FILES_MODULE_CONF_REQUEST:
1164       return new sfinx_8bit_t(tid);
1165     case SFINX_ELEMENT_32BIT:
1166     case SFINX_DELETE_SLICE_WITH_REATTACH:
1167     case SFINX_DELETE_SLICE_ASSOC_DATA:
1168     case SFINX_DELETE_SLICE_ASSOC_DATA_RECURSIVLY:
1169     case SFINX_DELETE_SLICE_MARK_DATA_UNSORTED:
1170     case SFINX_DELETE_SLICE_MARK_DATA_UNSORTED_RECURSIVLY:
1171     case SFINX_DELETE_SLICE_RECURSIVLY:
1172     case SFINX_EDIT_SLICE_REQUEST:
1173     case SFINX_SLICES_MODULE_TREE_REQUEST_EXCEPT:
1174     case SFINX_OBJECTS_TREE_REQUEST:
1175       return new sfinx_32bit_t(tid);
1176     case SFINX_ELEMENT_8BIT_VECTOR:
1177     case SFINX_DAEMON_VERSION:
1178     case SFINX_PACKET_CRYPT_TYPES:
1179     case SFINX_MIN_AUTH_LEVELS:
1180     case SFINX_MD5_SUM:
1181     case SFINX_AUTH_REQUEST:
1182       return new sfinx_8bit_vector_t(tid);
1183     case SFINX_ELEMENT_SLICE:
1184     case SFINX_EDIT_SLICE:
1185     case SFINX_NEW_SLICE:  
1186     case SFINX_SLICE_RELINK:
1187     case SFINX_NOTES_MODULE_TREE_REQUEST:  
1188       return new sfinx_slice_t(tid);
1189     case SFINX_ELEMENT_SLICE_VECTOR:
1190     case SFINX_SLICES_MODULE_TREE:
1191     case SFINX_SLICES_MODULE_TREE_EXCEPT:
1192     case SFINX_NOTES_MODULE_TREE:
1193     case SFINX_OBJECTS_TREE:
1194       return new sfinx_slice_vector_t(tid);
1195     case SFINX_ELEMENT_PAIR:
1196       return new sfinx_pair_t(tid);
1197     case SFINX_ELEMENT_PAIR_VECTOR:
1198     case SFINX_FILES_MODULE_CONF:
1199       return new sfinx_pair_vector_t(tid);
1200     case SFINX_ELEMENT_STRING:
1201     case SFINX_ALERT:
1202     case SFINX_FILES_MODULE_CLASSIFY_REPLY:
1203     case SFINX_FILES_MODULE_EDIT_REPLY:
1204     case SFINX_NOTES_MODULE_ADD_REPLY:
1205     case SFINX_NOTES_MODULE_EDIT_REPLY:
1206     case SFINX_FILES_MODULE_UNLINK:
1207       return new sfinx_string_t(tid);
1208     case SFINX_ELEMENT_FILE_VECTOR:
1209     case SFINX_FILES_MODULE_SORTED_TREE:
1210     case SFINX_FILES_MODULE_UNSORTED_TREE:
1211       return new sfinx_files_vector_t(tid);
1212     case SFINX_ELEMENT_PROGRESS:
1213       return new sfinx_progress_t(tid);
1214     case SFINX_ELEMENT_FILE:
1215     case SFINX_FILES_MODULE_CLASSIFY_REQUEST:
1216     case SFINX_FILES_MODULE_SORTED_TREE_REQUEST:
1217     case SFINX_FILES_MODULE_UNSORTED_TREE_REQUEST:
1218     case SFINX_FILES_MODULE_EDIT_FILE_REQUEST:
1219     case SFINX_FILES_MODULE_EDIT_FILE:
1220     case SFINX_FILES_MODULE_SORTED_UNLINK:
1221     case SFINX_FILES_MODULE_UNSORT:
1222       return new sfinx_file_t(tid);
1223     case SFINX_ELEMENT_SEARCH_QUERY:
1224       return new sfinx_search_query_t(tid);
1225     case SFINX_ELEMENT_SEARCH_RESULT:
1226       return new sfinx_pair_vector_t(tid);
1227     case SFINX_NOTES_MODULE_ADD:
1228       return new sfinx_note_t(tid);
1229     default:
1230       debug("Unknown element id 0x%x", tid);
1232   return 0;
1235 //sfinx_32bit_vector_t
1236 //sfinx_64bit_t
1237 //sfinx_64bit_vector_t
1238 //sfinx_float_t
1239 //sfinx_float_vector_t
1240 //sfinx_double_t
1241 //sfinx_double_vector_t
1242 //sfinx_string_vector_t
1243 //sfinx_date_t
1244 //sfinx_date_vector_t
1245 //sfinx_blob_t
1247 // TODO: - support for 64 bit lengths/values
1249 // ÎÅËÉÊ ÂÕÆÅÒ ÉÚ sfinx ÜÌÅÍÅÎÔÏ×
1250 class sfinx_elements {
1252   sfinx_size_t data_offset_, allocated_size_;
1253   u8_t *buf_;
1254   u32_t n_elements, current_element;
1255   // tree
1256   vector <sfinx_t *> elements;
1257   // u32_t curr_offset;
1259   public:
1260     u32_t count(sfinx_tid_t tid) {
1261       u32_t count_ = 0;
1262       for (u32_t i = 0; i < elements.size(); i++) {
1263         if (elements[i]->tid() == tid)
1264           count_++;
1265     }
1266       return count_;
1267    }
1268     sfinx_t *next() {
1269       if (current_element == elements.size())
1270         return 0;
1271       else
1272         return elements[current_element++];
1273    }
1274     sfinx_t *get(sfinx_tid_t el_id, u32_t el_offset = 0) {
1275       for (u32_t i = 0; i < elements.size(); i++) {
1276         // curr_offset = i;
1277         if (elements[i]->tid() == el_id) {
1278           if (!el_offset)
1279             return elements[i];
1280           else
1281             el_offset--;
1282        }
1283      }
1284       return 0;
1285    }
1286     // parse elements from binary buffer
1287     bool parse(u8_t *buf, u32_t buf_len) {
1288       u32_t current_position = 0;
1289       current_element = 0;
1290       s32_t buf_len_ = buf_len;
1291       while (buf_len_) {
1292         // id
1293         u32_t id_be32 = 0;
1294         u8_t first_byte = buf[current_position]; // id byte
1295         u8_t id_len = decoded_size(first_byte);
1296         memcpy(((u8_t *)&id_be32) + (sizeof(u32_t) - id_len), buf + current_position, id_len);
1297         sfinx_tid_t id = decode(id_be32, id_len);
1298         current_position += id_len;
1299         // len
1300         u32_t len_be32 = 0;
1301         first_byte = buf[current_position]; // len byte
1302         u8_t len_size = decoded_size(first_byte);
1303         memcpy(((u8_t *)&len_be32) + (sizeof(u32_t) - len_size), buf + current_position, len_size);
1304         u32_t len = decode(len_be32, len_size);
1305         current_position += len_size;
1306         buf_len_ -= (id_len + len_size + len);
1307         //debug("got object id %s,  id_len - %d, len_size - %d, object len - %d, buf_len - %d",
1308         //  sfinx_cmd2str(id), id_len, len_size, len, buf_len);
1309         if (!len)
1310           debug("Obj %s has zero len",  sfinx_cmd2str(id));
1311         if (buf_len_ < 0) {
1312           debug("Too small buf len");
1313           return 1;
1314        } else {
1315           sfinx_t *el;
1316           // allocate element
1317           el = make_sfinx_element(id);
1318           if (!el)
1319             return 1;
1320           if (len) {
1321             sfinx_size_t copied = el->get(buf + current_position, len);
1322             if (copied != len) {
1323               debug("%s parsing error, copied %lld from %d !",  sfinx_cmd2str(id), copied, len);
1324               delete el;
1325               return 1;
1326            }
1327          }
1328           elements.push_back(el);
1329           debug("parsed ok: object: %s, len - %d", sfinx_cmd2str(id), len);
1330         } // else buf_len is ok
1331         // data
1332         current_position += len;
1333      } // while
1334       return 0;
1335    }
1336     sfinx_elements() { buf_ = 0; clear(); }
1337     ~sfinx_elements() { clear(); }
1338     static s8_t decoded_size(u8_t first_byte) {
1339       u8_t mask = 0x80;
1340       for (s8_t size = 0; size < 4; size++) {
1341         if (first_byte & (mask >> size))
1342           return (size + 1);
1343      }
1344       return -1;
1345    }
1346     static s8_t coded_size(u32_t val) {
1347       if (val < 0x7F) // 2^7 - 1
1348         return 1;
1349       else if (val < 0x3FFFL) // 2^14 - 1
1350         return 2;
1351       else if (val < 0x1FFFFFL) // 2^21 - 1
1352         return 3;
1353       else if (val < 0x0FFFFFFFL) // 2^28 - 1
1354         return 4;
1355       else
1356         return -1;
1357    }
1358     // code value in utf8-like manner
1359     // returns be32 value
1360     static u32_t code(u32_t val, s8_t *coded_size_ = 0) {
1361       s8_t _coded_size_ = coded_size(val);
1362       if (_coded_size_ < 1)
1363         return 0;
1364       u8_t msb = (val >> ((_coded_size_ - 1) * 8)) & 0xFF;
1365       // code msb
1366       msb &= (0xFF >> (_coded_size_ - 1));
1367       msb |= (0x80 >> (_coded_size_ - 1));
1368       val &= ~(0xFFL << ((_coded_size_ - 1) * 8));
1369       val |= (msb << ((_coded_size_ - 1) * 8));
1370       if (coded_size_)
1371         *coded_size_ = _coded_size_;
1372       return htonl(val);
1373    }
1374     static u32_t decode(u32_t val_be32, s8_t decode_size) {
1375       val_be32 &= ~((0x80000000L >> (8 * (decode_size - 1))) >> (decode_size - 1));
1376       return ntohl(val_be32);
1377    }
1378     void clear() {
1379       data_offset_ = allocated_size_ = 0;
1380       if (buf_)
1381         delete [] buf_;
1382       buf_ = 0;
1383       n_elements = 0;
1384       for (u32_t i = 0; i < elements.size(); i++)
1385         delete elements[i];
1386       elements.clear();
1387       current_element = 0;
1388    }
1389     int add(sfinx_t &el) { return add(&el); }
1390     int add(sfinx_t *element) {
1391       s8_t element_id_size = -1, element_length_size = -1;
1392       u32_t coded_id_be32 = code(element->tid(), &element_id_size),
1393         coded_element_length_be32 = code(element->size(), &element_length_size);
1394       if ((element_id_size < 0) || (element_length_size < 0))
1395         return -1;
1396       sfinx_size_t space = element->size() + data_offset_ + element_id_size + element_length_size;
1397       if (space > allocated_size_) {
1398             space *= 1.2;
1399             u8_t *buf = new u8_t[space];
1400             if (allocated_size_) {
1401               memcpy(buf, buf_, allocated_size_);
1402               delete [] buf_;
1403            }
1404             allocated_size_ = space;
1405             buf_ = buf;
1406      }
1407       // add element id
1408       memcpy(buf_ + data_offset_, ((u8_t *)&coded_id_be32) + (sizeof(u32_t) - element_id_size),
1409         element_id_size);
1410       data_offset_ += element_id_size;
1411       // add element length
1412       memcpy(buf_ + data_offset_, ((u8_t *)&coded_element_length_be32) + (sizeof(u32_t) -
1413         element_length_size), element_length_size);
1414       data_offset_ += element_length_size;
1415       // add element data
1416       sfinx_size_t res = element->put(buf_ + data_offset_, allocated_size_ - data_offset_);
1417       if (res != element->size()) {
1418         debug("%s data copy error: buf_size - %lld, el_size - %lld, copied - %lld",
1419           sfinx_cmd2str(element->tid()), allocated_size_ - data_offset_, element->size(), res);
1420         return -3;
1421      }
1422       data_offset_ += element->size();
1423        debug("added %s, el_id_size - %d, el_len - %lld (be_len 0x%x), el_len_size - %d, "
1424          "copied - %lld, data_size in tx_buf - %lld", sfinx_cmd2str(element->tid()),
1425          element_id_size, element->size(), coded_element_length_be32, element_length_size,
1426          res, data_offset_);
1427       n_elements++;
1428       return 0;
1429    }
1430     sfinx_size_t size() { return data_offset_; }
1431     u8_t *buf() { return buf_; }
1434 #endif