libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers uc_global_data_type_registry.cpp Source File

uc_global_data_type_registry.cpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #include <uavcan/node/global_data_type_registry.hpp>
00006 #include <uavcan/debug.hpp>
00007 #include <cassert>
00008 #include <cstdlib>
00009 
00010 namespace uavcan
00011 {
00012 
00013 GlobalDataTypeRegistry::List* GlobalDataTypeRegistry::selectList(DataTypeKind kind) const
00014 {
00015     if (kind == DataTypeKindMessage)
00016     {
00017         return &msgs_;
00018     }
00019     else if (kind == DataTypeKindService)
00020     {
00021         return &srvs_;
00022     }
00023     else
00024     {
00025         UAVCAN_ASSERT(0);
00026         return UAVCAN_NULLPTR;
00027     }
00028 }
00029 
00030 GlobalDataTypeRegistry::RegistrationResult GlobalDataTypeRegistry::remove(Entry* dtd)
00031 {
00032     if (!dtd)
00033     {
00034         UAVCAN_ASSERT(0);
00035         return RegistrationResultInvalidParams;
00036     }
00037     if (isFrozen())
00038     {
00039         return RegistrationResultFrozen;
00040     }
00041 
00042     List* list = selectList(dtd->descriptor.getKind());
00043     if (!list)
00044     {
00045         return RegistrationResultInvalidParams;
00046     }
00047 
00048     list->remove(dtd);       // If this call came from regist<>(), that would be enough
00049     Entry* p = list->get();  // But anyway
00050     while (p)
00051     {
00052         Entry* const next = p->getNextListNode();
00053         if (p->descriptor.match(dtd->descriptor.getKind(), dtd->descriptor.getFullName()))
00054         {
00055             list->remove(p);
00056         }
00057         p = next;
00058     }
00059     return RegistrationResultOk;
00060 }
00061 
00062 GlobalDataTypeRegistry::RegistrationResult GlobalDataTypeRegistry::registImpl(Entry* dtd)
00063 {
00064     if (!dtd || !dtd->descriptor.isValid())
00065     {
00066         UAVCAN_ASSERT(0);
00067         return RegistrationResultInvalidParams;
00068     }
00069     if (isFrozen())
00070     {
00071         return RegistrationResultFrozen;
00072     }
00073 
00074     List* list = selectList(dtd->descriptor.getKind());
00075     if (!list)
00076     {
00077         return RegistrationResultInvalidParams;
00078     }
00079 
00080     {   // Collision check
00081         Entry* p = list->get();
00082         while (p)
00083         {
00084             if (p->descriptor.getID() == dtd->descriptor.getID()) // ID collision
00085             {
00086                 return RegistrationResultCollision;
00087             }
00088             if (!std::strncmp(p->descriptor.getFullName(), dtd->descriptor.getFullName(),
00089                               DataTypeDescriptor::MaxFullNameLen))                        // Name collision
00090             {
00091                 return RegistrationResultCollision;
00092             }
00093             p = p->getNextListNode();
00094         }
00095     }
00096 #if UAVCAN_DEBUG
00097     const unsigned len_before = list->getLength();
00098 #endif
00099     list->insertBefore(dtd, EntryInsertionComparator(dtd));
00100 
00101 #if UAVCAN_DEBUG
00102     {   // List integrity check
00103         const unsigned len_after = list->getLength();
00104         if ((len_before + 1) != len_after)
00105         {
00106             UAVCAN_ASSERT(0);
00107             std::abort();
00108         }
00109     }
00110     {   // Order check
00111         Entry* p = list->get();
00112         int id = -1;
00113         while (p)
00114         {
00115             if (id >= p->descriptor.getID().get())
00116             {
00117                 UAVCAN_ASSERT(0);
00118                 std::abort();
00119             }
00120             id = p->descriptor.getID().get();
00121             p = p->getNextListNode();
00122         }
00123     }
00124 #endif
00125     return RegistrationResultOk;
00126 }
00127 
00128 GlobalDataTypeRegistry& GlobalDataTypeRegistry::instance()
00129 {
00130     static GlobalDataTypeRegistry singleton;
00131     return singleton;
00132 }
00133 
00134 void GlobalDataTypeRegistry::freeze()
00135 {
00136     if (!frozen_)
00137     {
00138         frozen_ = true;
00139         UAVCAN_TRACE("GlobalDataTypeRegistry", "Frozen; num msgs: %u, num srvs: %u",
00140                      getNumMessageTypes(), getNumServiceTypes());
00141     }
00142 }
00143 
00144 const DataTypeDescriptor* GlobalDataTypeRegistry::find(const char* name) const
00145 {
00146     const DataTypeDescriptor* desc = find(DataTypeKindMessage, name);
00147     if (desc == UAVCAN_NULLPTR)
00148     {
00149         desc = find(DataTypeKindService, name);
00150     }
00151     return desc;
00152 }
00153 
00154 const DataTypeDescriptor* GlobalDataTypeRegistry::find(DataTypeKind kind, const char* name) const
00155 {
00156     if (!name)
00157     {
00158         UAVCAN_ASSERT(0);
00159         return UAVCAN_NULLPTR;
00160     }
00161     const List * list = selectList(kind);
00162     if (!list)
00163     {
00164         UAVCAN_ASSERT(0);
00165         return UAVCAN_NULLPTR;
00166     }
00167     Entry* p = list->get();
00168     while (p)
00169     {
00170         if (p->descriptor.match(kind, name))
00171         {
00172             return &p->descriptor;
00173         }
00174         p = p->getNextListNode();
00175     }
00176     return UAVCAN_NULLPTR;
00177 }
00178 
00179 const DataTypeDescriptor* GlobalDataTypeRegistry::find(DataTypeKind kind, DataTypeID dtid) const
00180 {
00181     const List * list = selectList(kind);
00182     if (!list)
00183     {
00184         UAVCAN_ASSERT(0);
00185         return UAVCAN_NULLPTR;
00186     }
00187     Entry* p = list->get();
00188     while (p)
00189     {
00190         if (p->descriptor.match(kind, dtid))
00191         {
00192             return &p->descriptor;
00193         }
00194         p = p->getNextListNode();
00195     }
00196     return UAVCAN_NULLPTR;
00197 }
00198 
00199 }