NCBI C++ ToolKit
compound_id.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: compound_id.cpp 87987 2019-10-29 17:07:52Z sadyrovr $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Dmitry Kazimirov
27  *
28  * File Description:
29  * Compound IDs are Base64-encoded string that contain application-specific
30  * information to identify and/or locate objects.
31  *
32  */
33 
34 /// @file compound_id.cpp
35 /// Implementations of CCompoundIDPool, CCompoundID, and CCompoundIDField.
36 
37 #include <ncbi_pch.hpp>
38 
39 #include "compound_id_impl.hpp"
40 
41 #include <connect/ncbi_socket.hpp>
42 
43 #include <iomanip>
44 
45 #define CIC_GENERICID_CLASS_NAME "CompoundID"
46 #define CIC_NETCACHEBLOBKEY_CLASS_NAME "NetCacheBlobKey"
47 #define CIC_NETSCHEDULEJOBKEY_CLASS_NAME "NetScheduleJobKey"
48 #define CIC_NETSTORAGEOBJECTLOC_CLASS_NAME_V1 "NetStorageObjectLocV1"
49 #define CIC_NETSTORAGEOBJECTLOC_CLASS_NAME "NetStorageObjectLoc"
50 
51 #define CIT_ID_TYPE_NAME "id"
52 #define CIT_INTEGER_TYPE_NAME "int"
53 #define CIT_SERVICE_NAME_TYPE_NAME "service"
54 #define CIT_DATABASE_NAME_TYPE_NAME "database"
55 #define CIT_TIMESTAMP_TYPE_NAME "time"
56 #define CIT_RANDOM_TYPE_NAME "rand"
57 #define CIT_IPV4_ADDRESS_TYPE_NAME "ipv4_addr"
58 #define CIT_HOST_TYPE_NAME "host"
59 #define CIT_PORT_TYPE_NAME "port"
60 #define CIT_IPV4_SOCK_ADDR_TYPE_NAME "ipv4_sock_addr"
61 #define CIT_OBJECTREF_TYPE_NAME "object"
62 #define CIT_STRING_TYPE_NAME "str"
63 #define CIT_BOOLEAN_TYPE_NAME "bool"
64 #define CIT_FLAGS_TYPE_NAME "flags"
65 #define CIT_LABEL_TYPE_NAME "label"
66 #define CIT_CUE_TYPE_NAME "cue"
67 #define CIT_SEQ_ID_TYPE_NAME "seq_id"
68 #define CIT_TAX_ID_TYPE_NAME "tax_id"
69 #define CIT_NESTED_CID_TYPE_NAME "nested"
70 
72 
73 static const char* s_ClassNames[eCIC_NumberOfClasses] = {
74  /* eCIC_GenericID */ CIC_GENERICID_CLASS_NAME,
75  /* eCIC_NetCacheBlobKey */ CIC_NETCACHEBLOBKEY_CLASS_NAME,
76  /* eCIC_NetScheduleJobKey */ CIC_NETSCHEDULEJOBKEY_CLASS_NAME,
77  /* eCIC_NetStorageObjectLocV1 */ CIC_NETSTORAGEOBJECTLOC_CLASS_NAME_V1,
78  /* eCIC_NetStorageObjectLoc */ CIC_NETSTORAGEOBJECTLOC_CLASS_NAME
79 };
80 
81 static const char* s_TypeNames[eCIT_NumberOfTypes] = {
82  /* eCIT_ID */ CIT_ID_TYPE_NAME,
83  /* eCIT_Integer */ CIT_INTEGER_TYPE_NAME,
84  /* eCIT_ServiceName */ CIT_SERVICE_NAME_TYPE_NAME,
85  /* eCIT_DatabaseName */ CIT_DATABASE_NAME_TYPE_NAME,
86  /* eCIT_Timestamp */ CIT_TIMESTAMP_TYPE_NAME,
87  /* eCIT_Random */ CIT_RANDOM_TYPE_NAME,
88  /* eCIT_IPv4Address */ CIT_IPV4_ADDRESS_TYPE_NAME,
89  /* eCIT_Host */ CIT_HOST_TYPE_NAME,
90  /* eCIT_Port */ CIT_PORT_TYPE_NAME,
91  /* eCIT_IPv4SockAddr */ CIT_IPV4_SOCK_ADDR_TYPE_NAME,
92  /* eCIT_ObjectRef */ CIT_OBJECTREF_TYPE_NAME,
93  /* eCIT_String */ CIT_STRING_TYPE_NAME,
94  /* eCIT_Boolean */ CIT_BOOLEAN_TYPE_NAME,
95  /* eCIT_Flags */ CIT_FLAGS_TYPE_NAME,
96  /* eCIT_Label */ CIT_LABEL_TYPE_NAME,
97  /* eCIT_Cue */ CIT_CUE_TYPE_NAME,
98  /* eCIT_SeqID */ CIT_SEQ_ID_TYPE_NAME,
99  /* eCIT_TaxID */ CIT_TAX_ID_TYPE_NAME,
100  /* eCIT_NestedCID */ CIT_NESTED_CID_TYPE_NAME
101 };
102 
104 {
105  switch (GetErrCode()) {
106  case eInvalidType:
107  return "eInvalidType";
108  default:
110  }
111 }
112 
114 {
115  m_CID = NULL;
116 }
117 
119 {
120  return m_Impl->m_Type;
121 }
122 
124 {
126  if (next != NULL)
127  next->m_CID = m_Impl->m_CID;
128  return next;
129 }
130 
132 {
134  if (next != NULL)
135  next->m_CID = m_Impl->m_CID;
136  return next;
137 }
138 
139 #define CIF_GET_IMPL(ret_type, method, type, member) \
140  CIF_GET_IMPL_(ret_type, method, type, m_Impl->m_Type != type, member)
141 
142 #define CIF_GET_IMPL_(ret_type, method, type, cond, member) \
143  ret_type CCompoundIDField::method() const \
144  { \
145  if (cond) { \
146  NCBI_THROW_FMT(CCompoundIDException, eInvalidType, \
147  "Compound ID field type mismatch (requested: " << \
148  s_TypeNames[type] << "; actual: " << \
149  s_TypeNames[m_Impl->m_Type] << ')'); \
150  } \
151  return (ret_type) m_Impl->member; \
152  }
153 
154 CIF_GET_IMPL(Uint8, GetID, eCIT_ID, m_Uint8Value)
156 CIF_GET_IMPL(string, GetServiceName, eCIT_ServiceName, m_StringValue)
157 CIF_GET_IMPL(string, GetDatabaseName, eCIT_DatabaseName, m_StringValue)
158 CIF_GET_IMPL(Int8, GetTimestamp, eCIT_Timestamp, m_Int8Value)
159 CIF_GET_IMPL(Uint4, GetRandom, eCIT_Random, m_Uint4Value)
160 CIF_GET_IMPL_(Uint4, GetIPv4Address, eCIT_IPv4Address, m_Impl->m_Type != eCIT_IPv4Address &&
161  m_Impl->m_Type != eCIT_IPv4SockAddr, m_IPv4SockAddr.m_IPv4Addr)
162 CIF_GET_IMPL(string, GetHost, eCIT_Host, m_StringValue)
163 CIF_GET_IMPL_(Uint2, GetPort, eCIT_Port, m_Impl->m_Type != eCIT_Port &&
164  m_Impl->m_Type != eCIT_IPv4SockAddr, m_IPv4SockAddr.m_Port)
165 CIF_GET_IMPL(string, GetObjectRef, eCIT_ObjectRef, m_StringValue)
166 CIF_GET_IMPL(string, GetString, eCIT_String, m_StringValue)
167 CIF_GET_IMPL(bool, GetBoolean, eCIT_Boolean, m_BoolValue)
168 CIF_GET_IMPL(Uint8, GetFlags, eCIT_Flags, m_Uint8Value)
169 CIF_GET_IMPL(string, GetLabel, eCIT_Label, m_StringValue)
170 CIF_GET_IMPL(Uint8, GetCue, eCIT_Cue, m_Uint8Value)
171 CIF_GET_IMPL(string, GetSeqID, eCIT_SeqID, m_StringValue)
172 CIF_GET_IMPL(Uint8, GetTaxID, eCIT_TaxID, m_Uint8Value)
173 CIF_GET_IMPL(const CCompoundID&, GetNestedCID, eCIT_NestedCID, m_NestedCID)
174 
175 
177  ECompoundIDFieldType field_type)
178 {
179  SCompoundIDFieldImpl* new_entry = m_Pool->m_FieldPool.Alloc();
180  m_FieldList.Append(new_entry);
181  m_HomogeneousFields[field_type].Append(new_entry);
182  new_entry->m_Type = field_type;
183  ++m_Length;
184  return new_entry;
185 }
186 
188 {
189  CCompoundIDPool pool(m_Pool);
190  m_Pool = NULL;
192  while (field != NULL) {
193  SCompoundIDFieldImpl* next_field = TFieldList::GetNext(field);
194  pool->m_FieldPool.ReturnToPool(field);
195  field = next_field;
196  }
197  pool->m_CompoundIDPool.ReturnToPool(this);
198 }
199 
201 {
202  CCompoundID cid(m_Impl->m_CID);
203  m_Impl->m_CID = NULL;
204  cid->Remove(m_Impl);
205 }
206 
208 {
209  return m_Impl->m_Class;
210 }
211 
213 {
214  return m_Impl->m_Length == 0;
215 }
216 
217 unsigned CCompoundID::GetLength() const
218 {
219  return m_Impl->m_Length;
220 }
221 
223 {
224  SCompoundIDFieldImpl* first = m_Impl->m_FieldList.m_Head;
225  first->m_CID = m_Impl;
226  return first;
227 }
228 
230 {
231  _ASSERT(field_type < eCIT_NumberOfTypes);
232 
234  m_Impl->m_HomogeneousFields[field_type].m_Head;
235  if (first != NULL)
236  first->m_CID = m_Impl;
237  return first;
238 }
239 
240 #define CID_APPEND_IMPL(method, field_type, val_type, member) \
241  void CCompoundID::method(val_type value) \
242  { \
243  m_Impl->AppendField(field_type)->member = value; \
244  }
245 
246 CID_APPEND_IMPL(AppendID, eCIT_ID, Uint8, m_Uint8Value)
247 CID_APPEND_IMPL(AppendInteger, eCIT_Integer, Int8, m_Int8Value)
248 CID_APPEND_IMPL(AppendServiceName, eCIT_ServiceName,
249  const string&, m_StringValue)
250 CID_APPEND_IMPL(AppendDatabaseName, eCIT_DatabaseName,
251  const string&, m_StringValue)
252 CID_APPEND_IMPL(AppendTimestamp, eCIT_Timestamp, Int8, m_Int8Value)
253 
254 void CCompoundID::AppendCurrentTime()
255 {
256  AppendTimestamp(time(NULL));
257 }
258 
259 CID_APPEND_IMPL(AppendRandom, eCIT_Random, Uint4, m_Uint4Value)
260 
261 void CCompoundID::AppendRandom()
262 {
263  AppendRandom(m_Impl->m_Pool->GetRand());
264 }
265 
266 CID_APPEND_IMPL(AppendIPv4Address, eCIT_IPv4Address,
267  Uint4, m_IPv4SockAddr.m_IPv4Addr)
268 CID_APPEND_IMPL(AppendHost, eCIT_Host, const string&, m_StringValue)
269 CID_APPEND_IMPL(AppendPort, eCIT_Port, Uint2, m_IPv4SockAddr.m_Port)
270 
271 void CCompoundID::AppendIPv4SockAddr(Uint4 ipv4_address, Uint2 port_number)
272 {
273  SCompoundIDFieldImpl* new_field = m_Impl->AppendField(eCIT_IPv4SockAddr);
274  new_field->m_IPv4SockAddr.m_IPv4Addr = ipv4_address;
275  new_field->m_IPv4SockAddr.m_Port = port_number;
276 }
277 
278 CID_APPEND_IMPL(AppendObjectRef, eCIT_ObjectRef, const string&, m_StringValue)
279 CID_APPEND_IMPL(AppendString, eCIT_String, const string&, m_StringValue)
280 CID_APPEND_IMPL(AppendBoolean, eCIT_Boolean, bool, m_BoolValue)
281 CID_APPEND_IMPL(AppendFlags, eCIT_Flags, Uint8, m_Uint8Value)
282 CID_APPEND_IMPL(AppendLabel, eCIT_Label, const string&, m_StringValue)
283 CID_APPEND_IMPL(AppendCue, eCIT_Cue, Uint8, m_Uint8Value)
284 CID_APPEND_IMPL(AppendSeqID, eCIT_SeqID, const string&, m_StringValue)
285 CID_APPEND_IMPL(AppendTaxID, eCIT_TaxID, Uint8, m_Uint8Value)
286 CID_APPEND_IMPL(AppendNestedCID, eCIT_NestedCID,
287  const CCompoundID&, m_NestedCID)
288 
290 {
291  SCompoundIDFieldImpl* last = m_Impl->m_FieldList.m_Tail;
292  last->m_CID = m_Impl;
293  return last;
294 }
295 
297 {
298  return m_Impl->PackV0();
299 }
300 
301 static void s_Indent(CNcbiOstrstream& sstr,
302  int indent_depth, const char* indent)
303 {
304  while (--indent_depth >= 0)
305  sstr << indent;
306 }
307 
308 static void s_DumpCompoundID(CNcbiOstrstream& sstr, SCompoundIDImpl* cid_impl,
309  int indent_depth, const char* indent)
310 {
311  sstr << s_ClassNames[cid_impl->m_Class] << '\n';
312  s_Indent(sstr, indent_depth, indent);
313  sstr << "{\n";
314 
315  SCompoundIDFieldImpl* field = cid_impl->m_FieldList.m_Head;
316 
317  if (field != NULL)
318  for (;;) {
319  s_Indent(sstr, indent_depth + 1, indent);
320  sstr << s_TypeNames[field->m_Type] << ' ';
321  switch (field->m_Type) {
322  case eCIT_ID:
323  case eCIT_Cue:
324  case eCIT_TaxID:
325  sstr << field->m_Uint8Value;
326  break;
327  case eCIT_Integer:
328  case eCIT_Timestamp:
329  sstr << field->m_Int8Value;
330  break;
331  case eCIT_ServiceName:
332  case eCIT_DatabaseName:
333  case eCIT_Host:
334  case eCIT_ObjectRef:
335  case eCIT_String:
336  case eCIT_Label:
337  case eCIT_SeqID:
338  sstr << '"' <<
339  NStr::PrintableString(field->m_StringValue) << '"';
340  break;
341  case eCIT_Random:
342  sstr << field->m_Uint4Value;
343  break;
344  case eCIT_IPv4Address:
345  sstr << CSocketAPI::ntoa(field->m_IPv4SockAddr.m_IPv4Addr);
346  break;
347  case eCIT_Port:
348  sstr << field->m_IPv4SockAddr.m_Port;
349  break;
350  case eCIT_IPv4SockAddr:
351  sstr << CSocketAPI::ntoa(field->m_IPv4SockAddr.m_IPv4Addr) <<
352  ':' << field->m_IPv4SockAddr.m_Port;
353  break;
354  case eCIT_Boolean:
355  sstr << (field->m_BoolValue ? "true" : "false");
356  break;
357  case eCIT_Flags:
358  if (field->m_Uint8Value <= 0xFF)
359  sstr << "0b" << setw(8) << setfill('0') <<
360  NStr::UInt8ToString(field->m_Uint8Value, 0, 2);
361  else if (field->m_Uint8Value <= 0xFFFF)
362  sstr << "0b" << setw(16) << setfill('0') <<
363  NStr::UInt8ToString(field->m_Uint8Value, 0, 2);
364  else
365  sstr << "0x" <<
366  NStr::UInt8ToString(field->m_Uint8Value, 0, 16);
367  break;
368  case eCIT_NestedCID:
369  s_DumpCompoundID(sstr, field->m_NestedCID,
370  indent_depth + 1, indent);
371  break;
372 
373  case eCIT_NumberOfTypes:
374  _ASSERT(0);
375  break;
376  }
377  field = cid_impl->m_FieldList.GetNext(field);
378  if (field != NULL)
379  sstr << ",\n";
380  else {
381  sstr << '\n';
382  break;
383  }
384  }
385 
386  s_Indent(sstr, indent_depth, indent);
387  sstr << '}';
388 }
389 
391 {
392  CNcbiOstrstream sstr;
393  s_DumpCompoundID(sstr, m_Impl, 0, " ");
394  sstr << '\n' << NcbiEnds;
395  return CNcbiOstrstreamToString(sstr);
396 }
397 
399 {
400  m_Impl->m_RandomGen.Randomize();
401 }
402 
404 {
405  CCompoundID new_cid(m_Impl->m_CompoundIDPool.Alloc());
406  new_cid->Reset(m_Impl, new_id_class);
407  return new_cid;
408 }
409 
411 {
412  return m_Impl->UnpackV0(cid);
413 }
414 
416 {
417 public:
419  const string& cid_dump) :
420  m_Pool(cid_pool),
421  m_Dump(cid_dump),
422  m_Ch(m_Dump.c_str()),
423  m_Line(1),
425  {
426  }
427 
429 
430  void SkipSpace();
431  void SkipSpaceToNextToken();
432  void CheckEOF();
433 
434 private:
436  bool x_EOF() const {return *m_Ch == '\0';}
437  string x_ReadString();
438  Uint8 x_ReadUint8();
439  Uint8 x_ReadInt8();
442 
444  string m_Dump;
445  const char* m_Ch;
446  size_t m_Line;
447  const char* m_LineBegin;
448  size_t m_ErrLine;
449  const char* m_ErrPos;
450 };
451 
452 #define CID_PARSER_EXCEPTION(message) \
453  NCBI_THROW_FMT(CCompoundIDException, eInvalidDumpSyntax, \
454  "line " << m_ErrLine << ", column " << \
455  (m_ErrPos - m_LineBegin + 1) << ": " << message)
456 
458 {
459  SkipSpace();
460  x_SaveErrPos();
461 
462  if (x_EOF() || !isalpha(*m_Ch)) {
463  CID_PARSER_EXCEPTION("missing compound ID class name");
464  }
465 
466  const char* token_begin = m_Ch;
467 
468  do
469  ++m_Ch;
470  while (!x_EOF() && isalpha(*m_Ch));
471 
472  CTempString new_id_class_name(token_begin, m_Ch - token_begin);
473 
474  ECompoundIDClass new_id_class = eCIC_NumberOfClasses;
475 
476  switch (*token_begin) {
477  case 'C':
478  if (new_id_class_name == CIC_GENERICID_CLASS_NAME)
479  new_id_class = eCIC_GenericID;
480  break;
481  case 'N':
482  if (new_id_class_name == CIC_NETCACHEBLOBKEY_CLASS_NAME)
483  new_id_class = eCIC_NetCacheBlobKey;
484  else if (new_id_class_name == CIC_NETSCHEDULEJOBKEY_CLASS_NAME)
485  new_id_class = eCIC_NetScheduleJobKey;
486  else if (new_id_class_name == CIC_NETSTORAGEOBJECTLOC_CLASS_NAME)
487  new_id_class = eCIC_NetStorageObjectLoc;
488  else if (new_id_class_name == CIC_NETSTORAGEOBJECTLOC_CLASS_NAME_V1)
489  new_id_class = eCIC_NetStorageObjectLocV1;
490  }
491 
492  if (new_id_class == eCIC_NumberOfClasses) {
493  CID_PARSER_EXCEPTION("unknown compound ID class '" <<
494  new_id_class_name << '\'');
495  }
496 
497  SkipSpace();
498 
499  if (x_EOF() || *m_Ch != '{') {
500  x_SaveErrPos();
501  CID_PARSER_EXCEPTION("missing '{'");
502  }
503 
504  ++m_Ch;
505 
507 
508  CCompoundID result(m_Pool.NewID(new_id_class));
509 
510  if (*m_Ch != '}')
511  for (;;) {
512  token_begin = m_Ch;
513  x_SaveErrPos();
514 
515  do
516  ++m_Ch;
517  while (isalnum(*m_Ch) || *m_Ch == '_');
518 
519  CTempString field_type_name(token_begin, m_Ch - token_begin);
520 
522 
523  switch (*token_begin) {
524  case '}':
525  CID_PARSER_EXCEPTION("a field type name is required");
526  case 'b':
527  if (field_type_name == CIT_BOOLEAN_TYPE_NAME)
528  field_type = eCIT_Boolean;
529  break;
530  case 'd':
531  if (field_type_name == CIT_DATABASE_NAME_TYPE_NAME)
532  field_type = eCIT_DatabaseName;
533  break;
534  case 'f':
535  if (field_type_name == CIT_FLAGS_TYPE_NAME)
536  field_type = eCIT_Flags;
537  break;
538  case 'h':
539  if (field_type_name == CIT_HOST_TYPE_NAME)
540  field_type = eCIT_Host;
541  break;
542  case 'i':
543  if (field_type_name == CIT_ID_TYPE_NAME)
544  field_type = eCIT_ID;
545  else if (field_type_name == CIT_INTEGER_TYPE_NAME)
546  field_type = eCIT_Integer;
547  else if (field_type_name == CIT_IPV4_ADDRESS_TYPE_NAME)
548  field_type = eCIT_IPv4Address;
549  else if (field_type_name == CIT_IPV4_SOCK_ADDR_TYPE_NAME)
550  field_type = eCIT_IPv4SockAddr;
551  break;
552  case 'n':
553  if (field_type_name == CIT_NESTED_CID_TYPE_NAME)
554  field_type = eCIT_NestedCID;
555  else if (field_type_name == CIT_CUE_TYPE_NAME)
556  field_type = eCIT_Cue;
557  break;
558  case 'p':
559  if (field_type_name == CIT_OBJECTREF_TYPE_NAME)
560  field_type = eCIT_ObjectRef;
561  else if (field_type_name == CIT_PORT_TYPE_NAME)
562  field_type = eCIT_Port;
563  break;
564  case 'r':
565  if (field_type_name == CIT_RANDOM_TYPE_NAME)
566  field_type = eCIT_Random;
567  break;
568  case 's':
569  if (field_type_name == CIT_SEQ_ID_TYPE_NAME)
570  field_type = eCIT_SeqID;
571  else if (field_type_name == CIT_SERVICE_NAME_TYPE_NAME)
572  field_type = eCIT_ServiceName;
573  else if (field_type_name == CIT_STRING_TYPE_NAME)
574  field_type = eCIT_String;
575  break;
576  case 't':
577  if (field_type_name == CIT_LABEL_TYPE_NAME)
578  field_type = eCIT_Label;
579  else if (field_type_name == CIT_TAX_ID_TYPE_NAME)
580  field_type = eCIT_TaxID;
581  else if (field_type_name == CIT_TIMESTAMP_TYPE_NAME)
582  field_type = eCIT_Timestamp;
583  }
584 
585  if (field_type == eCIT_NumberOfTypes) {
586  CID_PARSER_EXCEPTION("unknown field type '" <<
587  field_type_name << '\'');
588  }
589 
591 
592  switch (field_type) {
593  case eCIT_ID:
594  result.AppendID(x_ReadUint8());
595  break;
596  case eCIT_Integer:
597  result.AppendInteger(x_ReadInt8());
598  break;
599  case eCIT_ServiceName:
600  result.AppendServiceName(x_ReadString());
601  break;
602  case eCIT_DatabaseName:
603  result.AppendDatabaseName(x_ReadString());
604  break;
605  case eCIT_Timestamp:
606  result.AppendTimestamp(x_ReadInt8());
607  break;
608  case eCIT_Random:
609  {
610  x_SaveErrPos();
611  Uint8 random_number = x_ReadUint8();
612  if (random_number >= ((Uint8) 1) << 8 * sizeof(Uint4)) {
614  "random number exceeds maximum allowed value");
615  }
616  result.AppendRandom((Uint4) random_number);
617  }
618  break;
619  case eCIT_IPv4Address:
620  result.AppendIPv4Address(x_ReadIPv4Address());
621  break;
622  case eCIT_Host:
623  result.AppendHost(x_ReadString());
624  break;
625  case eCIT_Port:
626  result.AppendPort(x_ReadPortNumber());
627  break;
628  case eCIT_IPv4SockAddr:
629  {
630  Uint4 ipv4_address = x_ReadIPv4Address();
631  if (x_EOF() || *m_Ch != ':') {
632  x_SaveErrPos();
633  CID_PARSER_EXCEPTION("missing ':'");
634  }
635  ++m_Ch;
636  result.AppendIPv4SockAddr(ipv4_address, x_ReadPortNumber());
637  }
638  break;
639  case eCIT_ObjectRef:
640  result.AppendObjectRef(x_ReadString());
641  break;
642  case eCIT_String:
643  result.AppendString(x_ReadString());
644  break;
645  case eCIT_Boolean:
646  {
647  token_begin = m_Ch;
648  x_SaveErrPos();
649 
650  while (!x_EOF() && isalpha(*m_Ch))
651  ++m_Ch;
652 
653  CTempString bool_val(token_begin, m_Ch - token_begin);
654 
655  if (bool_val == "false")
656  result.AppendBoolean(false);
657  else if (bool_val == "true")
658  result.AppendBoolean(true);
659  else {
660  CID_PARSER_EXCEPTION("invalid boolean value \"" <<
661  bool_val << '\"');
662  }
663  }
664  break;
665  case eCIT_Flags:
666  result.AppendFlags(x_ReadUint8());
667  break;
668  case eCIT_Label:
669  result.AppendLabel(x_ReadString());
670  break;
671  case eCIT_Cue:
672  result.AppendCue(x_ReadUint8());
673  break;
674  case eCIT_SeqID:
675  result.AppendSeqID(x_ReadString());
676  break;
677  case eCIT_TaxID:
678  result.AppendTaxID(x_ReadUint8());
679  break;
680  case eCIT_NestedCID:
681  result.AppendNestedCID(ParseID());
682  break;
683  case eCIT_NumberOfTypes:
684  break;
685  }
686 
688 
689  if (*m_Ch == ',')
690  ++m_Ch;
691  else if (*m_Ch == '}')
692  break;
693  else {
694  x_SaveErrPos();
695  CID_PARSER_EXCEPTION("either ',' or '}' expected");
696  }
697 
699  }
700  ++m_Ch;
701  return result;
702 }
703 
705 {
706  while (!x_EOF() && isspace(*m_Ch))
707  if (*m_Ch++ == '\n') {
708  m_LineBegin = m_Ch;
709  ++m_Line;
710  }
711 }
712 
714 {
715  for (;;)
716  if (x_EOF()) {
717  x_SaveErrPos();
718  CID_PARSER_EXCEPTION("unterminated compound ID");
719  } else if (!isspace(*m_Ch))
720  break;
721  else if (*m_Ch++ == '\n') {
722  m_LineBegin = m_Ch;
723  ++m_Line;
724  }
725 }
726 
728 {
729  if (!x_EOF()) {
730  x_SaveErrPos();
731  CID_PARSER_EXCEPTION("extra characters past component ID definition");
732  }
733 }
734 
736 {
737  char quote_char;
738 
739  if (x_EOF() || ((quote_char = *m_Ch) != '"' && quote_char != '\'')) {
740  x_SaveErrPos();
741  CID_PARSER_EXCEPTION("string must start with a quote character");
742  }
743 
744  const char* str_begin = ++m_Ch;
745  bool escaped = false;
746 
747  while (!x_EOF())
748  if (*m_Ch == quote_char && !escaped)
749  return NStr::ParseEscapes(
750  CTempString(str_begin, m_Ch++ - str_begin));
751  else if (*m_Ch == '\\') {
752  escaped = !escaped;
753  ++m_Ch;
754  } else {
755  escaped = false;
756  if (*m_Ch++ == '\n') {
757  m_LineBegin = m_Ch;
758  ++m_Line;
759  }
760  }
761 
762  x_SaveErrPos();
763  CID_PARSER_EXCEPTION("unterminated quoted string");
764 }
765 
767 {
768  x_SaveErrPos();
769 
770  if (x_EOF() || !isdigit(*m_Ch)) {
771  CID_PARSER_EXCEPTION("missing integer value");
772  }
773 
774  const char* token_begin;
775  int base;
776 
777  if (*m_Ch != '0') {
778  token_begin = m_Ch;
779  ++m_Ch; // A digit other than '0', moving on...
780  base = 10;
781  } else {
782  ++m_Ch; // Skip the leading zero.
783 
784  if (x_EOF())
785  return 0;
786 
787  switch (*m_Ch) {
788  case 'b':
789  case 'B':
790  token_begin = ++m_Ch;
791  base = 2;
792  break;
793  case 'x':
794  case 'X':
795  token_begin = ++m_Ch;
796  base = 16;
797  break;
798  default:
799  if (!isdigit(*m_Ch))
800  return 0;
801  token_begin = m_Ch;
802  ++m_Ch; // It's a digit; move on to the next character.
803  base = 8;
804  }
805  }
806 
807  while (!x_EOF() && isalnum(*m_Ch))
808  ++m_Ch;
809 
811  m_Ch - token_begin), NStr::fConvErr_NoThrow, base);
812 
813  if (result == 0 && errno != 0) {
814  CID_PARSER_EXCEPTION("invalid Uint8 number specification");
815  }
816 
817  return result;
818 }
819 
821 {
822  const char* token_begin = m_Ch;
823  x_SaveErrPos();
824 
825  if (!x_EOF() && *m_Ch == '-')
826  ++m_Ch;
827 
828  if (x_EOF() || !isdigit(*m_Ch)) {
829  x_SaveErrPos();
830  CID_PARSER_EXCEPTION("missing integer value");
831  }
832 
833  do
834  ++m_Ch;
835  while (!x_EOF() && isdigit(*m_Ch));
836 
838  m_Ch - token_begin), NStr::fConvErr_NoThrow);
839 
840  if (result == 0 && errno != 0) {
841  CID_PARSER_EXCEPTION("integer overflow");
842  }
843 
844  return result;
845 }
846 
848 {
849  x_SaveErrPos();
850  Uint4 ipv4_address = 0;
851  unsigned char* octet = reinterpret_cast<unsigned char*>(&ipv4_address);
852  unsigned number;
853  int dots = 3;
854  do {
855  if (x_EOF())
856  goto IPv4ParsingError;
857  number = *m_Ch - '0';
858  if (number > 9)
859  goto IPv4ParsingError;
860  for (;;) {
861  ++m_Ch;
862  if (x_EOF())
863  goto IPv4ParsingError;
864  unsigned digit = *m_Ch - '0';
865  if (digit <= 9) {
866  if ((number = number * 10 + digit) > 255)
867  goto IPv4ParsingError;
868  } else if (*m_Ch == '.') {
869  ++m_Ch;
870  break;
871  } else
872  goto IPv4ParsingError;
873  }
874  *octet++ = (unsigned char) number;
875  } while (--dots > 0);
876  if (x_EOF())
877  goto IPv4ParsingError;
878  number = *m_Ch - '0';
879  if (number > 9)
880  goto IPv4ParsingError;
881  for (;;) {
882  ++m_Ch;
883  if (x_EOF())
884  break;
885  unsigned digit = *m_Ch - '0';
886  if (digit <= 9) {
887  if ((number = number * 10 + digit) > 255)
888  goto IPv4ParsingError;
889  } else {
890  if (*m_Ch == '.')
891  ++m_Ch;
892  break;
893  }
894  }
895  *octet = (unsigned char) number;
896  return ipv4_address;
897 
898 IPv4ParsingError:
899  CID_PARSER_EXCEPTION("invalid IPv4 address");
900 }
901 
903 {
904  x_SaveErrPos();
905  Uint8 port_number = x_ReadUint8();
906  if (port_number >= 1 << 8 * sizeof(Uint2)) {
907  CID_PARSER_EXCEPTION("port number exceeds maximum value");
908  }
909  return (Uint2) port_number;
910 }
911 
912 CCompoundID CCompoundIDPool::FromDump(const string& cid_dump)
913 {
914  CCompoundIDDumpParser dump_parser(m_Impl, cid_dump);
915 
916  CCompoundID result(dump_parser.ParseID());
917 
918  dump_parser.SkipSpace();
919  dump_parser.CheckEOF();
920 
921  return result;
922 }
923 
924 #define SCRAMBLE_PASS() \
925  pos = seq; \
926  counter = seq_len - 1; \
927  do { \
928  pos[1] = (unsigned char)(pos[1] ^ *pos ^ length_factor--); \
929  ++pos; \
930  } while (--counter > 0);
931 
932 static void s_Scramble(unsigned char* seq, size_t seq_len)
933 {
934  if (seq_len > 1) {
935  unsigned char length_factor = (unsigned char)(((unsigned char) seq_len << 1) - 1);
936  unsigned char* pos;
937  size_t counter;
938 
939  SCRAMBLE_PASS();
940 
941  *seq = (unsigned char)(*seq ^ *pos ^ length_factor--);
942 
943  SCRAMBLE_PASS();
944  }
945 }
946 
947 void g_PackID(void* binary_id, size_t binary_id_len, string& packed_id)
948 {
949  s_Scramble((unsigned char*) binary_id, binary_id_len);
950 
951  size_t packed_id_len;
952 
953  base64url_encode(NULL, binary_id_len, NULL, 0, &packed_id_len);
954 
955  packed_id.resize(packed_id_len);
956 
957  packed_id[0] = '\0';
958 
959  base64url_encode(binary_id, binary_id_len,
960  const_cast<char*>(packed_id.data()), packed_id_len, NULL);
961 }
962 
963 #define UNSCRAMBLE_PASS() \
964  counter = seq_len - 1; \
965  do { \
966  *pos = (unsigned char)(*pos ^ pos[-1] ^ ++length_factor); \
967  --pos; \
968  } while (--counter > 0);
969 
970 static void s_Unscramble(unsigned char* seq, size_t seq_len)
971 {
972  if (seq_len > 1) {
973  unsigned char length_factor = 0;
974  unsigned char* pos = seq + seq_len - 1;
975  size_t counter;
976 
977  UNSCRAMBLE_PASS();
978 
979  pos = seq + seq_len - 1;
980 
981  *seq = (unsigned char)(*seq ^ *pos ^ ++length_factor);
982 
983  UNSCRAMBLE_PASS();
984  }
985 }
986 
987 bool g_UnpackID(const string& packed_id, string& binary_id)
988 {
989  size_t binary_id_len;
990 
991  base64url_decode(NULL, packed_id.length(), NULL, 0, &binary_id_len);
992 
993  binary_id.resize(binary_id_len);
994  binary_id[0] = '\0';
995 
996  unsigned char* ptr = (unsigned char*) const_cast<char*>(binary_id.data());
997 
998  if (base64url_decode(packed_id.data(), packed_id.length(),
999  ptr, binary_id_len, NULL) != eBase64_OK)
1000  return false;
1001 
1002  s_Unscramble(ptr, binary_id_len);
1003 
1004  return true;
1005 }
1006 
const char * m_LineBegin
CCompoundID ParseID()
CCompoundIDPool m_Pool
CCompoundIDDumpParser(CCompoundIDPool::TInstance cid_pool, const string &cid_dump)
@ eInvalidType
Field type mismatch.
Definition: compound_id.hpp:94
virtual const char * GetErrCodeString() const override
Get error code interpreted as text.
Compound ID field – an element of the compound ID that has a type and a value.
CCompoundIDField GetNextHomogeneous()
Return the next field of the same type.
CCompoundIDField GetNextNeighbor()
Return the next immediately adjacent field.
void Remove()
Remove this field from the compound ID that contains it.
ECompoundIDFieldType GetType()
Return the type of this field.
CNetRef< SCompoundIDFieldImpl > m_Impl
Pool of recycled CCompoundID objects.
CNetRef< SCompoundIDPoolImpl > m_Impl
CCompoundID NewID(ECompoundIDClass new_id_class)
Create and return a new CCompoundID objects.
CCompoundID FromString(const string &cid)
Unpack the base64-encoded ID and return a CCompoundID object for field extraction.
CCompoundIDPool()
Construct a new pool of CompoundID objects.
CCompoundID FromDump(const string &cid_dump)
Restore the compound ID from its textual representation created by CCompoundID::Dump().
Base64-encoded ID string that contains extractable typed fields.
CCompoundIDField GetFirstField()
Return the first field or NULL if this ID is empty.
CCompoundIDField GetFirst(ECompoundIDFieldType field_type)
Return the first field of the specified type or NULL if this compound ID contains no fields of such t...
string Dump()
Dump the contents of the ID in the human-readable format that can also be parsed by CCompoundIDPool::...
CNetRef< SCompoundIDImpl > m_Impl
string ToString()
Pack the ID and return its string representation.
unsigned GetLength() const
Return the number of fields this ID contains.
bool IsEmpty() const
Return TRUE if this compound ID contains no fields.
ECompoundIDClass GetClass() const
One of the registered ID classes.
CNcbiOstrstreamToString class helps convert CNcbiOstrstream to a string Sample usage:
Definition: ncbistre.hpp:802
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
#define CIT_SEQ_ID_TYPE_NAME
Definition: compound_id.cpp:67
#define CIC_NETSCHEDULEJOBKEY_CLASS_NAME
Definition: compound_id.cpp:47
#define CIT_STRING_TYPE_NAME
Definition: compound_id.cpp:62
#define CIT_NESTED_CID_TYPE_NAME
Definition: compound_id.cpp:69
void g_PackID(void *binary_id, size_t binary_id_len, string &packed_id)
#define CIT_DATABASE_NAME_TYPE_NAME
Definition: compound_id.cpp:54
#define CIT_OBJECTREF_TYPE_NAME
Definition: compound_id.cpp:61
static const char * s_TypeNames[eCIT_NumberOfTypes]
Definition: compound_id.cpp:81
#define CIT_IPV4_SOCK_ADDR_TYPE_NAME
Definition: compound_id.cpp:60
#define CIF_GET_IMPL(ret_type, method, type, member)
#define CIT_TAX_ID_TYPE_NAME
Definition: compound_id.cpp:68
#define CIT_RANDOM_TYPE_NAME
Definition: compound_id.cpp:56
#define CIT_SERVICE_NAME_TYPE_NAME
Definition: compound_id.cpp:53
#define CIT_CUE_TYPE_NAME
Definition: compound_id.cpp:66
#define CIC_NETSTORAGEOBJECTLOC_CLASS_NAME
Definition: compound_id.cpp:49
#define UNSCRAMBLE_PASS()
#define CIT_INTEGER_TYPE_NAME
Definition: compound_id.cpp:52
#define CIT_FLAGS_TYPE_NAME
Definition: compound_id.cpp:64
#define CIC_GENERICID_CLASS_NAME
Definition: compound_id.cpp:45
#define CIT_LABEL_TYPE_NAME
Definition: compound_id.cpp:65
bool g_UnpackID(const string &packed_id, string &binary_id)
#define CID_PARSER_EXCEPTION(message)
static void s_Unscramble(unsigned char *seq, size_t seq_len)
#define CIF_GET_IMPL_(ret_type, method, type, cond, member)
#define CIT_HOST_TYPE_NAME
Definition: compound_id.cpp:58
#define CIC_NETSTORAGEOBJECTLOC_CLASS_NAME_V1
Definition: compound_id.cpp:48
static void s_DumpCompoundID(CNcbiOstrstream &sstr, SCompoundIDImpl *cid_impl, int indent_depth, const char *indent)
static const char * s_ClassNames[eCIC_NumberOfClasses]
Definition: compound_id.cpp:73
#define CID_APPEND_IMPL(method, field_type, val_type, member)
#define CIT_PORT_TYPE_NAME
Definition: compound_id.cpp:59
#define CIT_IPV4_ADDRESS_TYPE_NAME
Definition: compound_id.cpp:57
#define CIT_TIMESTAMP_TYPE_NAME
Definition: compound_id.cpp:55
#define CIC_NETCACHEBLOBKEY_CLASS_NAME
Definition: compound_id.cpp:46
static void s_Indent(CNcbiOstrstream &sstr, int indent_depth, const char *indent)
#define CIT_BOOLEAN_TYPE_NAME
Definition: compound_id.cpp:63
#define CIT_ID_TYPE_NAME
Definition: compound_id.cpp:51
static void s_Scramble(unsigned char *seq, size_t seq_len)
#define SCRAMBLE_PASS()
ECompoundIDFieldType
Definition: compound_id.hpp:62
@ eCIT_Timestamp
Definition: compound_id.hpp:67
@ eCIT_Host
Definition: compound_id.hpp:70
@ eCIT_Cue
Definition: compound_id.hpp:78
@ eCIT_SeqID
Definition: compound_id.hpp:79
@ eCIT_IPv4SockAddr
Definition: compound_id.hpp:72
@ eCIT_Port
Definition: compound_id.hpp:71
@ eCIT_ObjectRef
Definition: compound_id.hpp:73
@ eCIT_String
Definition: compound_id.hpp:74
@ eCIT_Integer
Definition: compound_id.hpp:64
@ eCIT_DatabaseName
Definition: compound_id.hpp:66
@ eCIT_Label
Definition: compound_id.hpp:77
@ eCIT_Random
Definition: compound_id.hpp:68
@ eCIT_Boolean
Definition: compound_id.hpp:75
@ eCIT_ID
Definition: compound_id.hpp:63
@ eCIT_TaxID
Definition: compound_id.hpp:80
@ eCIT_Flags
Definition: compound_id.hpp:76
@ eCIT_IPv4Address
Definition: compound_id.hpp:69
@ eCIT_ServiceName
Definition: compound_id.hpp:65
@ eCIT_NumberOfTypes
Definition: compound_id.hpp:83
@ eCIT_NestedCID
Definition: compound_id.hpp:81
ECompoundIDClass
Definition: compound_id.hpp:50
@ eCIC_NumberOfClasses
Definition: compound_id.hpp:57
@ eCIC_NetScheduleJobKey
Definition: compound_id.hpp:53
@ eCIC_GenericID
Definition: compound_id.hpp:51
@ eCIC_NetCacheBlobKey
Definition: compound_id.hpp:52
@ eCIC_NetStorageObjectLocV1
Old version of NetStorageObjectLoc.
Definition: compound_id.hpp:54
@ eCIC_NetStorageObjectLoc
Definition: compound_id.hpp:55
Internal declarations of the CompoundID classes.
bool GetSeqID(const CRef< CSeq_align > &seqAlign, CRef< CSeq_id > &SeqID, bool getSlave=true)
Definition: cuAlign.cpp:55
static DLIST_TYPE *DLIST_NAME() first(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:46
static DLIST_TYPE *DLIST_NAME() last(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:51
static DLIST_TYPE *DLIST_NAME() next(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:56
#define NULL
Definition: ncbistd.hpp:225
TErrCode GetErrCode(void) const
Get error code.
Definition: ncbiexpt.cpp:453
virtual const char * GetErrCodeString(void) const
Get error code interpreted as text.
Definition: ncbiexpt.cpp:444
string GetLabel(const CSeq_id &id)
uint32_t Uint4
4-byte (32-bit) unsigned integer
Definition: ncbitype.h:103
uint16_t Uint2
2-byte (16-bit) unsigned integer
Definition: ncbitype.h:101
int64_t Int8
8-byte (64-bit) signed integer
Definition: ncbitype.h:104
uint64_t Uint8
8-byte (64-bit) unsigned integer
Definition: ncbitype.h:105
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static string ntoa(unsigned int host)
BSD-like API. NB: when int, "host" must be in network byte order.
#define NcbiEnds
Definition: ncbistre.hpp:549
static string PrintableString(const CTempString str, TPrintableMode mode=fNewLine_Quote|fNonAscii_Passthru)
Get a printable version of the specified string.
Definition: ncbistr.cpp:3953
static Int8 StringToInt8(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to Int8.
Definition: ncbistr.cpp:793
static string ParseEscapes(const CTempString str, EEscSeqRange mode=eEscSeqRange_Standard, char user_char='?')
Parse C-style escape sequences in the specified string.
Definition: ncbistr.cpp:4793
static Uint8 StringToUInt8(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to Uint8.
Definition: ncbistr.cpp:873
static string UInt8ToString(Uint8 value, TNumToStringFlags flags=0, int base=10)
Convert UInt8 to string.
Definition: ncbistr.hpp:5168
@ fConvErr_NoThrow
Do not throw an exception on error.
Definition: ncbistr.hpp:285
unsigned short GetPort() const
Get the listening port number back.
unsigned short m_Port
TCP port to listen on.
Uint4 GetHost(TEndpointKey key)
int isalpha(Uchar c)
Definition: ncbictype.hpp:61
int isspace(Uchar c)
Definition: ncbictype.hpp:69
int isalnum(Uchar c)
Definition: ncbictype.hpp:62
int isdigit(Uchar c)
Definition: ncbictype.hpp:64
static BOOL number
Definition: pcregrep.c:193
string indent(" ")
#define base64url_encode
Definition: ncbi_base64.h:44
@ eBase64_OK
Transcoded successfully.
Definition: ncbi_base64.h:100
#define base64url_decode
Definition: ncbi_base64.h:45
ECompoundIDFieldType m_Type
struct SCompoundIDFieldImpl::@975::@977 m_IPv4SockAddr
virtual void DeleteThis()
Virtual method "deleting" this object.
void Reset(SCompoundIDPoolImpl *pool, ECompoundIDClass id_class)
virtual void DeleteThis()
Virtual method "deleting" this object.
void Remove(SCompoundIDFieldImpl *field)
ECompoundIDClass m_Class
CCompoundIDPool m_Pool
void ReturnToPool(Poolable *element)
SCompoundIDObjectPool< SCompoundIDImpl, ECompoundIDClass > m_CompoundIDPool
SCompoundIDObjectPool< SCompoundIDFieldImpl, ECompoundIDFieldType > m_FieldPool
SCompoundIDFieldImpl * m_Head
static SCompoundIDFieldImpl * GetNext(SCompoundIDFieldImpl *entry)
static bool GetInteger(wxSpinCtrl *spinctrl, int *value)
#define _ASSERT
else result
Definition: token2.c:20
#define const
Definition: zconf.h:232
Modified on Wed Apr 17 13:08:55 2024 by modify_doxy.py rev. 669887