Beispiel #1
0
//========================================================================
void AHexEditorActor::BeginPlay()
{
	Super::BeginPlay();

	AHexTileActor::Init(m_RootTileCoordinates);

	m_Grid.InsertElement({ 0, 0 }, this);

	EnableInput(GetWorld()->GetFirstPlayerController());
	
	SwitchBindings(InputMode::Expanding);

	FVector locator(0, 0, 0);
	m_ArrowsParent = GetWorld()->SpawnActor(AActor::StaticClass());

	m_ArrowsParent->SetRootComponent(NewObject<USceneComponent>(m_ArrowsParent,TEXT("ArrowsParent")));

	for (int i = 0; i < 6; ++i)
	{
		FVector locator(0, 0, 0);
		FRotator rot(0, 60 * -i, 0);
		auto* actor = GetWorld()->SpawnActor(ExpansionArrowActor, &locator, &rot);
		m_Arrows[i] = CastChecked<AStaticMeshActor>(actor);
		m_Arrows[i]->GetStaticMeshComponent()->SetVisibility(false);
		m_Arrows[i]->GetStaticMeshComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
		m_Arrows[i]->GetStaticMeshComponent()->SetMobility(EComponentMobility::Movable);
		auto* arrowComp = m_Arrows[i]->FindComponentByClass<UExpandArrowComponent>();
		check(arrowComp);
		arrowComp->SetRelativeDirection(i);
		m_Arrows[i]->GetStaticMeshComponent()->OnClicked.AddDynamic(arrowComp, &UExpandArrowComponent::OnClick);
		m_Arrows[i]->AttachRootComponentToActor(m_ArrowsParent);
	}
}
Beispiel #2
0
char Fl_XmlTokenizer::read_char()
{
	if(locator()) locator()->m_col++;
    read_buf_pos++;
    fill_buffer();
    return read_buf[read_buf_pos];
}
Beispiel #3
0
void AbstractAssembler::bind(Label& L) {
  if (L.is_bound()) {
    // Assembler can bind a label more than once to the same place.
    guarantee(L.loc() == locator(), "attempt to redefine label");
    return;
  }
  L.bind_loc(locator());
  L.patch_instructions((MacroAssembler*)this);
}
void CompilersFoundDlg::MSWUpdateToolchain(CompilerPtr compiler)
{
    wxUnusedVar(compiler);
#ifdef __WXMSW__
    if(compiler->GetCompilerFamily() == COMPILER_FAMILY_MINGW) {
        // Clang and VC lacks 2 tools: make and windres
        // so we copy those from the default MinGW compiler
        wxString make = compiler->GetTool("MAKE");
        wxString resourceCompiler = compiler->GetTool("ResourceCompiler");

        for(size_t i = 0; i < m_allCompilers.size(); ++i) {
            CompilerPtr c = m_allCompilers.at(i);
            if(c->GetCompilerFamily() == COMPILER_FAMILY_CLANG || c->GetCompilerFamily() == COMPILER_FAMILY_VC) {
                c->SetTool("MAKE", make);
                c->SetTool("ResourceCompiler", resourceCompiler);

                if(c->GetCompilerFamily() == COMPILER_FAMILY_CLANG) {
                    // Clang under Windows, needs the include paths from the MinGW compiler
                    IncludePathLocator locator(NULL);
                    wxArrayString includePaths, excludePaths;
                    locator.Locate(includePaths, excludePaths, false, compiler->GetTool("CXX"));

                    // Convert the include paths to semi colon separated list
                    wxString mingwIncludePaths = wxJoin(includePaths, ';');
                    c->SetGlobalIncludePath(mingwIncludePaths);
                }
            }
        }
    }
#endif
}
Beispiel #5
0
PyObject* Preprocessor_set_include_locator(Preprocessor *self, PyObject *args)
{
    PyObject *locator_;
    if (!PyArg_ParseTuple(args, "O:set_include_locator", &locator_))
        return NULL;

    if (!PyCallable_Check(locator_))
    {
        PyErr_SetString(PyExc_TypeError, "Expected a callable");
        return NULL;
    }

    try
    {
        boost::shared_ptr<cmonster::core::IncludeLocator> locator(
            new cmonster::python::IncludeLocator(locator_));
        self->preprocessor->set_include_locator(locator);
        Py_INCREF(Py_None);
        return Py_None;
    }
    catch (...)
    {
        set_python_exception();
        return NULL;
    }
}
Beispiel #6
0
    Response::Response(const char *stream, std::size_t size)
        : status_code_(0),
          status_code_type_(0),
          http_version_(0),
          reason_phrase_(),
          content_buffer_()
    {
        try
        {
            assert(stream);
            StatusLine status_line(stream, stream + size);
            status_code_ = status_line.GetStatusCode();
            status_code_type_ = status_line.GetStatusCodeType();
            http_version_ = status_line.GetHttpVersion();
            reason_phrase_ = status_line.GetReasonPhrase();

            ContentLocator locator(stream, size);
            const char *content_begin_pos = locator.GetContentBeginPos();
            std::size_t content_length = locator.GetContentLength();
            content_buffer_.assign(content_begin_pos, content_begin_pos + content_length);
        }
        catch (...)
        {
            throw ResponseException(std::string(stream, size));
        }
    }
QMessageContentContainer QMessageContentContainer::find(const QMessageContentContainerId &id) const
{
    QMessageContentContainer container;

    QMailMessagePart::Location location(convert(id));

    if (location.isValid(false)) {
        PartLocator locator(location);
        d_ptr->_container->foreachPart<PartLocator&>(locator);

        if (locator._part) {
            container.d_ptr->_part = *locator._part;
            container.d_ptr->_container = &container.d_ptr->_part;
        }
    } else {
        if (location.containingMessageId() == convert(d_ptr->_message)->id()) {
            // Create a part containing the body content of this message
            QMailMessage *message(convert(d_ptr->_message));
            QMailMessageContentDisposition cd(QMailMessageContentDisposition::Inline);
            container.d_ptr->_part = QMailMessagePart::fromData(message->body().data(), cd, message->contentType(), QMailMessageBody::Base64);
            container.d_ptr->_container = &container.d_ptr->_part;
        }
    }

    return container;
}
Beispiel #8
0
void switch_tile(const std::string& tile)
{
	terrain_prefix = game_config::terrain::form_img_prefix(tile);
	mask_surf = get_image(terrain_prefix + game_config::terrain::short_mask);
	grid_top = locator(terrain_prefix + game_config::terrain::short_grid_top);
	grid_bottom = locator(terrain_prefix + game_config::terrain::short_grid_bottom);

	if (tile == game_config::tile_hex) {
		scale_ratio_w = scale_ratio * 3 / 4;
		scale_ratio_h = scale_ratio;
		minimap_tile_dst = minimap_tile_dst_hex;
	} else {
		scale_ratio_w = scale_ratio;
		scale_ratio_h = scale_ratio;
		minimap_tile_dst = minimap_tile_dst_square;
	}
}
int CodeBuffer::locator(address addr) const {
  for (int n = 0; n < (int)SECT_LIMIT; n++) {
    const CodeSection* cs = code_section(n);
    if (cs->allocates(addr)) {
      return locator(addr - cs->start(), n);
    }
  }
  return -1;
}
bool QMessageContentContainer::contains(const QMessageContentContainerId &id) const
{
    QMailMessagePart::Location location(convert(id));

    if (location.isValid(false)) {
        PartLocator locator(location);
        d_ptr->_container->foreachPart<PartLocator&>(locator);
        return (locator._part != 0);
    } else {
        return (location.containingMessageId() == convert(d_ptr->_message)->id());
    }
}
Beispiel #11
0
void trackMode(ServoManager& sm) {
    PersonTracker pt;
    std::cout << "[*] Loading camera settings\n";
    if(!pt.loadSettings()) {
        std::cerr << "Error on loading settings\n";
        return;
    }
    if(!pt.open()) {
        std::cerr << "Error on open camera\n";
        return;
    }
    pt.setCascade("/etc/mechanical_eyes/faces.xml");

    GPIOClass ledGPIO("5");
    ledGPIO.export_gpio();
    ledGPIO.setdir_gpio("out");
    ledGPIO.setval_gpio("0");

    std::vector<cv::Rect> faces;
    timespec last_face_found, current, start;
    bool posnull = true;
    clock_gettime(CLOCK_REALTIME, &start);
    while(1) {
        faces.clear();
//        std::cerr << "Searching...\n";
        if(pt.getFaces(faces) && faces.size()) {
            ledGPIO.setval_gpio("1");
            PersonRelativeLocator locator(pt.getLastImg().size());
            
            cv::Point2f loc = locator.locate(faces.at(0));
            std::cout << "Face found at " << loc.x << "," << loc.y << std::endl;

            sm.setHorizontal(loc.x);
            sm.setVertical(loc.y);
            clock_gettime(CLOCK_REALTIME, &last_face_found);
            posnull = false;
        } else if(!posnull) {
            ledGPIO.setval_gpio("0");
            // drive to pos null after 30 sec without a face
            clock_gettime(CLOCK_REALTIME, &current);
            if(current.tv_sec - last_face_found.tv_sec > 30) {
                posnull = true;
                sm.nullPositions();
                clock_gettime(CLOCK_REALTIME, &start);
            }
        } else if(posnull) {
            clock_gettime(CLOCK_REALTIME, &current);
            float time = current.tv_sec - start.tv_sec + (current.tv_nsec - start.tv_nsec) / 1e9f;
            lookAround(sm, time);
        }
    }
}
BOOST_AUTO_TEST_CASE_TEMPLATE(PublisherKeySelector, T, InMemoryStorages)
{
  T ims;

  Name name("/insert/withkey");
  shared_ptr<Data> data = makeData(name);
  ims.insert(*data);

  shared_ptr<Interest> interest = makeInterest(name);
  Name keyName("/somewhere/key");

  ndn::KeyLocator locator(keyName);
  interest->setPublisherPublicKeyLocator(locator);

  shared_ptr<const Data> found = ims.find(*interest);
  BOOST_CHECK(found == nullptr);
}
Beispiel #13
0
void Connection::open(const tstring& host, const tstring& login, const tstring& password, const tstring& nmspace)
{
	ASSERT(!isOpen());

	// Format the full connection path.
	tstring path = host + nmspace;

	if (path.compare(0, 2, TXT("\\\\")) != 0)
		path = TXT("\\\\") + path;

	// Create the connection.
	IWbemServicesPtr	services;
	IWbemLocatorPtr		locator(CLSID_WbemLocator);
	WCL::ComStr			bstrPath(path);
	WCL::ComStr			bstrAuth(TXT(""));
	HRESULT				result;

	if (login.empty())
	{
		result = locator->ConnectServer(bstrPath.Get(), nullptr, nullptr, nullptr, 0,
										bstrAuth.Get(), nullptr, AttachTo(services));
	}
	else
	{
		WCL::ComStr	bstrLogin(login);
		WCL::ComStr	bstrPassword(password);

		result = locator->ConnectServer(bstrPath.Get(), bstrLogin.Get(), bstrPassword.Get(), nullptr, 0,
										bstrAuth.Get(), nullptr, AttachTo(services));
	}

	if (FAILED(result))
		throw Exception(result, locator, Core::fmt(TXT("Failed to connect to the WMI provider on '%s'"), host.c_str()).c_str());

	// Enable impersonation on the connection.
    result = ::CoSetProxyBlanket(services.get(), RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, nullptr,
									RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
									nullptr, EOAC_NONE);

	if (FAILED(result))
		throw Exception(result, locator, TXT("Failed to enable impersonation on the WMI connection"));

	// Update state.
	m_locator  = locator;
	m_services = services;
}
CompilerPtr CompilerLocatorCLANG::Locate(const wxString& folder)
{
    m_compilers.clear();
    wxFileName clang(folder, "clang");
#ifdef __WXMSW__
    clang.SetExt("exe");
#endif
    bool found = clang.FileExists();
    if ( ! found ) {
        // try to see if we have a bin folder here
        clang.AppendDir("bin");
        found = clang.FileExists();
    }
    
    if ( found ) {
        CompilerPtr compiler( new Compiler(NULL) );
        compiler->SetCompilerFamily(COMPILER_FAMILY_CLANG);
        // get the compiler version
        compiler->SetName( GetCompilerFullName(clang.GetFullPath() ) );
        compiler->SetGenerateDependeciesFile(true);
        m_compilers.push_back( compiler );
        clang.RemoveLastDir();
        AddTools(compiler, clang.GetPath());
        
        // Update the toolchain (if Windows)
#ifdef __WXMSW__
        CompilerPtr defaultMinGWCmp = BuildSettingsConfigST::Get()->GetDefaultCompiler(COMPILER_FAMILY_MINGW);
        if ( defaultMinGWCmp ) {
            compiler->SetTool("MAKE", defaultMinGWCmp->GetTool("MAKE"));
            compiler->SetTool("ResourceCompiler", defaultMinGWCmp->GetTool("ResourceCompiler"));
            
            // Update the include paths
            IncludePathLocator locator(NULL);
            wxArrayString includePaths, excludePaths;
            locator.Locate(includePaths, excludePaths, false, defaultMinGWCmp->GetTool("CXX"));
            
            // Convert the include paths to semi colon separated list
            wxString mingwIncludePaths = wxJoin(includePaths, ';');
            compiler->SetGlobalIncludePath( mingwIncludePaths );
        }
#endif
        return compiler;
    }
    return NULL;
}
Beispiel #15
0
void ApplyObjects(Pmwx& ioMap)
{
	if (gFAAObs.empty()) return;

	Point_2	sw, ne;
	CalcBoundingBox(ioMap, sw, ne);
// 	ioMap.Index();

	int	placed = 0;

//	CGAL::Arr_landmarks_point_location<Arrangement_2>	locator(gMap);
	CGAL::Arr_walk_along_line_point_location<Arrangement_2>	locator(gMap);

	for (FAAObsTable::iterator i = gFAAObs.begin(); i != gFAAObs.end(); ++i)
	{
		if (i->second.kind != NO_VALUE)
		{
			Point_2 loc = Point_2(i->second.lon, i->second.lat);

			DebugAssert(CGAL::is_valid(gMap));
			CGAL::Object obj = locator.locate(loc);
			Face_const_handle ff;
			if(CGAL::assign(ff,obj))
			{
				Face_handle f = ioMap.non_const_handle(ff);
				GISPointFeature_t	feat;
					feat.mFeatType = i->second.kind;
					feat.mLocation = loc;
					if (i->second.agl != DEM_NO_DATA)
						feat.mParams[pf_Height] = i->second.agl;
					feat.mInstantiated = false;
					f->data().mPointFeatures.push_back(feat);
					++placed;
	#if 0
					printf("Placed %s at %lf, %lf\n",
						FetchTokenString(i->second.kind), i->second.lon, i->second.lat);
	#endif
//				if (v.size() > 1)
//					fprintf(stderr,"WARNING (%d,%d): Point feature %lf, %lf matches multiple areas.\n",gMapWest, gMapSouth, CGAL::to_double(loc.x()), CGAL::to_double(loc.y()));

			}
		}
	}
	printf("Placed %d objects.\n", placed);
}
Beispiel #16
0
CStatsTracker* CGameScopes::PushGameScope(size_t scopeID, uint32 timestamp, CGameStatistics* gameStatistics)
{
	CRY_ASSERT(scopeID < m_scopeRegistry.size());
	if(scopeID >= m_scopeRegistry.size())
		return 0;

	// Check that same scope isn't already on the stack
	size_t pos = FindScopePos(scopeID);
	CRY_ASSERT_MESSAGE(pos == m_scopeStack.size(), "Same scope can't be pushed twice");
	if(pos != m_scopeStack.size())
		return 0;

	SNodeLocator locator(scopeID);
	locator.timeStamp = timestamp;
	CStatsTracker* tracker = new CStatsTracker(locator, gameStatistics);
	m_scopeStack.push_back(SScopeData(locator, tracker));

	return tracker;
}
void CompilersDetectorManager::MSWFixClangToolChain(CompilerPtr compiler,
                                                    const ICompilerLocator::CompilerVec_t& allCompilers)
{
// Update the toolchain (if Windows)
#ifdef __WXMSW__
    ICompilerLocator::CompilerVec_t compilers;
    if(allCompilers.empty()) {
        BuildSettingsConfigCookie cookie;
        CompilerPtr cmp = BuildSettingsConfigST::Get()->GetFirstCompiler(cookie);
        while(cmp) {
            compilers.push_back(cmp);
            cmp = BuildSettingsConfigST::Get()->GetNextCompiler(cookie);
        }
    } else {
        compilers.insert(compilers.end(), allCompilers.begin(), allCompilers.end());
    }

    if(compiler->GetCompilerFamily() == COMPILER_FAMILY_CLANG) {
        for(size_t i = 0; i < compilers.size(); ++i) {
            CompilerPtr mingwCmp = compilers.at(i);
            if(mingwCmp->GetCompilerFamily() == COMPILER_FAMILY_MINGW) {
                compiler->SetTool("MAKE", mingwCmp->GetTool("MAKE"));
                compiler->SetTool("ResourceCompiler", mingwCmp->GetTool("ResourceCompiler"));

                // Update the include paths
                IncludePathLocator locator(NULL);
                wxArrayString includePaths, excludePaths;
                locator.Locate(includePaths, excludePaths, false, mingwCmp->GetTool("CXX"));

                // Convert the include paths to semi colon separated list
                wxString mingwIncludePaths = wxJoin(includePaths, ';');
                compiler->SetGlobalIncludePath(mingwIncludePaths);

                // Keep the mingw's bin path
                wxFileName mingwGCC(mingwCmp->GetTool("CXX"));
                compiler->SetPathVariable(mingwGCC.GetPath());
                break;
            }
        }
    }
#endif
}
Beispiel #18
0
void CResourceLoader::addLoader(std::string mountPoint, shared_ptr<ISimpleResourceLoader> loader, bool writeable)
{
	LoaderEntry loaderEntry;
	loaderEntry.loader = loader;
	loaderEntry.prefix = mountPoint;
	loaderEntry.writeable = writeable;
	loaders.push_back(loaderEntry);

	// Get entries and add them to the resources list
	const boost::unordered_map<ResourceID, std::string> & entries = loader->getEntries();

	boost::to_upper(mountPoint);

	BOOST_FOREACH (auto & entry, entries)
	{
		// Create identifier and locator and add them to the resources list
		ResourceID ident(mountPoint, entry.first.getName(), entry.first.getType());
		ResourceLocator locator(loader.get(), entry.second);

		resources[ident].push_back(locator);
	}
Beispiel #19
0
void StyleTask::write_record( void )
{

   const char
      *localstr = locator();

#ifdef FISH_DEBUG
   DBUG_PRINT("Style",
	      ("Style Sheet: \nview=`%s'\nonlineSS=`%s'\n\nprintSS=`%s'\n",
	       localstr,
	       onlineSS->GetBuffer(),
	       printSS->GetBuffer() ));

   DBUG_PRINT("Style", ("View id...\n"));
   DBUG_PRINT("Style", ("\tis: `%s'\n", localstr ));
#endif

   CC_String *str = new CC_String( localstr );
   int *bogus = new int(0);
   if ( !viewset->contains( str ) ) {
      viewset->insertKeyAndValue( str,bogus );
   }
   else {
     Token::signalError(Token::User, Token::Continuable, 0, 0,
			"Duplicate stylesheet id `%s'", localstr);
     return;
   }
   
   int online_bufsize=onlineSS->GetSize();
   const char *online_buf = onlineSS->GetBuffer();

   int print_bufsize= printSS->GetSize();
   const char *print_buf = printSS->GetBuffer();

   done(localstr,
	online_buf, online_bufsize,
	print_buf, print_bufsize);
}
Beispiel #20
0
   std::string path::toElementText( xml_document const& _doc )const {

      path key_no_attr = *this;

      if( key_no_attr.points_to_attr() ) {
         path_element& pel = key_no_attr.last();
         pel.attr( path_attr() );
      }// debug

      string pathadd = key_no_attr;

      if( pathadd == "domain.features.apic" ) {
         pathadd = key_no_attr;
      }

      element_locator locator( key_no_attr );

      _doc.accept( &locator );

      xml_element* elem = locator.elementfound();

      if( elem != nullptr ) {
         xml_node const* ch = elem->first_child();

         if( ch == nullptr ) {
            return "nullptr";
         }

         xml_text const* p1 = dynamic_cast<xml_text const*>( ch );
         string txt = p1->value();
         return txt;

      }


      return "";

   }
Beispiel #21
0
asset_bundle::handle_ptr png_asset_bundle::get(std::string const& name,
                                               asset_manager::context const& ctx) const {
    // TODO:
    auto asset_name = name + ".png";
    if (!locator()->contains(asset_name))
        return nullptr;

    std::shared_ptr<png_asset_bundle const> thiz(shared_from_this(), this);
    return handle_ptr(new texture_handle([=] (texture::ptr& tex, asset_collection&) {
        // TODO: auto detect the image type and load (A8/RGB565/RGBA8888)
        png_loader png;
        auto img = png.do_load(thiz->locator()->from(asset_name).get(), image_desc::RGBA8888);
        tex = thiz->_device->create_texture(img.desc.size,{
            texture::T2D, texture::RGBA8888,
            texture::Clamp, texture::Clamp,
            texture::NearestLinear, texture::Nearest,
            1
        });
        tex->load(img.data().get(), texture::RGBA8888);
        
        // auto-fill all the mipmaps for png textures
        tex->generate_mipmap();
    }));
}
Beispiel #22
0
void CuttingPlane::recurseSelfIntersectAndDivide(float z, vector<locator> &EndPointStack, vector<outline> &outlines, vector<locator> &visited)
{
	// pop an entry from the stack.
	// Trace it till it hits itself
	//		store a outline
	// When finds splits, store locator on stack and recurse

	while(EndPointStack.size())
	{
		locator start(EndPointStack.back().p, EndPointStack.back().v, EndPointStack.back().t);
		visited.push_back(start);	// add to visited list
		EndPointStack.pop_back();	// remove from to-do stack

		// search for the start point

		outline result;
		for(int p = start.p; p < (int)offsetPolygons.size(); p++)
		{
			for(int v = start.v; v < (int)offsetPolygons[p].points.size(); v++)
			{
				Vector2f P1 = offsetVertices[offsetPolygons[p].points[v]];
				Vector2f P2 = offsetVertices[offsetPolygons[p].points[(v+1)%offsetPolygons[p].points.size()]];

				result.push_back(P1);	// store this point
				for(int p2=0; p2 < (int)offsetPolygons.size(); p2++)
				{
					int count2 = offsetPolygons[p2].points.size();
					for(int v2 = 0; v2 < count2; v2++)
					{
						if((p==p2) && (v == v2))	// Dont check a point against itself
							continue;
						Vector2f P3 = offsetVertices[offsetPolygons[p2].points[v2]];
						Vector2f P4 = offsetVertices[offsetPolygons[p2].points[(v2+1)%offsetPolygons[p2].points.size()]];
						InFillHit hit;

						if(P1 != P3 && P2 != P3 && P1 != P4 && P2 != P4)
						{
							if(IntersectXY(P1,P2,P3,P4,hit))
							{
								bool alreadyVisited=false;

								size_t i;
								for(i=0;i<visited.size();i++)
								{
									if(visited[i].p == p && visited[i].v == v)
									{
										alreadyVisited = true;
										break;
									}
								}
								if(alreadyVisited == false)
								{
									EndPointStack.push_back(locator(p,v+1,hit.t));	// continue from here later on
									p=p2;v=v2;	// continue along the intersection line
									Vector2f P1 = offsetVertices[offsetPolygons[p].points[v]];
									Vector2f P2 = offsetVertices[offsetPolygons[p].points[(v+1)%offsetPolygons[p].points.size()]];
								}


								result.push_back(hit.p);
								// Did we hit the starting point?
								if (start.p == p && start.v == v) // we have a loop
								{
									outlines.push_back(result);
									result.clear();
									recurseSelfIntersectAndDivide(z, EndPointStack, outlines, visited);
									return;
								}
								glPointSize(10);
								glColor3f(1,1,1);
								glBegin(GL_POINTS);
								glVertex3f(hit.p.x, hit.p.y, z);
								glEnd();
							}
						}
					}
				}
			}
		}
	}
}
/*----------------------------------------------------------------------
|   AP4_Processor::Process
+---------------------------------------------------------------------*/
AP4_Result
AP4_Processor::Process(AP4_ByteStream&   input, 
                       AP4_ByteStream&   output,
                       AP4_ByteStream*   fragments,
                       ProgressListener* listener,
                       AP4_AtomFactory&  atom_factory)
{
    // read all atoms.
    // keep all atoms except [mdat]
    // keep a ref to [moov]
    // put [moof] atoms in a separate list
    AP4_AtomParent              top_level;
    AP4_MoovAtom*               moov = NULL;
    AP4_ContainerAtom*          mfra = NULL;
    AP4_SidxAtom*               sidx = NULL;
    AP4_List<AP4_AtomLocator>   frags;
    AP4_UI64                    stream_offset = 0;
    bool                        in_fragments = false;
    unsigned int                sidx_count = 0;
    for (AP4_Atom* atom = NULL;
        AP4_SUCCEEDED(atom_factory.CreateAtomFromStream(input, atom));
        input.Tell(stream_offset)) {
        if (atom->GetType() == AP4_ATOM_TYPE_MDAT) {
            delete atom;
            continue;
        } else if (atom->GetType() == AP4_ATOM_TYPE_MOOV) {
            moov = AP4_DYNAMIC_CAST(AP4_MoovAtom, atom);
            if (fragments) break;
        } else if (atom->GetType() == AP4_ATOM_TYPE_MFRA) {
            mfra = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
            continue;
        } else if (atom->GetType() == AP4_ATOM_TYPE_SIDX) {
            // don't keep the index, it is likely to be invalidated, we will recompute it later
            ++sidx_count;
            if (sidx == NULL) {
                sidx = AP4_DYNAMIC_CAST(AP4_SidxAtom, atom);
            } else {
                delete atom;
                continue;
            }
        } else if (atom->GetType() == AP4_ATOM_TYPE_SSIX) {
            // don't keep the index, it is likely to be invalidated
            delete atom;
            continue;
        } else if (!fragments && (in_fragments || atom->GetType() == AP4_ATOM_TYPE_MOOF)) {
            in_fragments = true;
            frags.Add(new AP4_AtomLocator(atom, stream_offset));
			break;
        }
        top_level.AddChild(atom);
    }

    // check that we have at most one sidx (we can't deal with multi-sidx streams here
    if (sidx_count > 1) {
        top_level.RemoveChild(sidx);
        delete sidx;
        sidx = NULL;
    }
    
    // if we have a fragments stream, get the fragment locators from there
    if (fragments) {
        stream_offset = 0;
        for (AP4_Atom* atom = NULL;
            AP4_SUCCEEDED(atom_factory.CreateAtomFromStream(*fragments, atom));
            fragments->Tell(stream_offset)) {
            if (atom->GetType() == AP4_ATOM_TYPE_MDAT) {
                delete atom;
                continue;
            }
            frags.Add(new AP4_AtomLocator(atom, stream_offset));
        }
    }
    
    // initialize the processor
    AP4_Result result = Initialize(top_level, input);
    if (AP4_FAILED(result)) return result;

    // process the tracks if we have a moov atom
    AP4_Array<AP4_SampleLocator> locators;
    AP4_Cardinal                 track_count       = 0;
    AP4_List<AP4_TrakAtom>*      trak_atoms        = NULL;
    AP4_LargeSize                mdat_payload_size = 0;
    AP4_SampleCursor*            cursors           = NULL;
    if (moov) {
        // build an array of track sample locators
        trak_atoms = &moov->GetTrakAtoms();
        track_count = trak_atoms->ItemCount();
        cursors = new AP4_SampleCursor[track_count];
		m_TrackData.SetItemCount(track_count);
		m_StreamData.SetItemCount(1);
		m_StreamData[0].stream = &input;

		unsigned int index = 0;
        for (AP4_List<AP4_TrakAtom>::Item* item = trak_atoms->FirstItem(); item; item=item->GetNext()) {
            AP4_TrakAtom* trak = item->GetData();

            // find the stsd atom
            AP4_ContainerAtom* stbl = AP4_DYNAMIC_CAST(AP4_ContainerAtom, trak->FindChild("mdia/minf/stbl"));
            if (stbl == NULL) continue;
            
            // see if there's an external data source for this track
            AP4_ByteStream* trak_data_stream = &input;
            for (AP4_List<ExternalTrackData>::Item* ditem = m_ExternalTrackData.FirstItem(); ditem; ditem=ditem->GetNext()) {
                ExternalTrackData* tdata = ditem->GetData();
                if (tdata->m_TrackId == trak->GetId()) {
                    trak_data_stream = tdata->m_MediaData;
                    break;
                }
            }
			AP4_ContainerAtom *mvex = AP4_DYNAMIC_CAST(AP4_ContainerAtom, moov->GetChild(AP4_ATOM_TYPE_MVEX));
			AP4_TrexAtom*      trex = NULL;
			if (mvex) {
				for (AP4_List<AP4_Atom>::Item* item = mvex->GetChildren().FirstItem(); item; item = item->GetNext()) {
					AP4_Atom* atom = item->GetData();
					if (atom->GetType() == AP4_ATOM_TYPE_TREX) {
						trex = AP4_DYNAMIC_CAST(AP4_TrexAtom, atom);
						if (trex && trex->GetTrackId() == trak->GetId()) 
							break;
						trex = NULL;
					}
				}
			}
			// create the track handler    
            m_TrackData[index].track_handler	= CreateTrackHandler(trak, trex);
			m_TrackData[index].new_id = trak->GetId();

			cursors[index].m_Locator.m_TrakIndex   = index;
            cursors[index].m_Locator.m_SampleTable = new AP4_AtomSampleTable(stbl, *trak_data_stream);
            cursors[index].m_Locator.m_SampleIndex = 0;
            cursors[index].m_Locator.m_ChunkIndex  = 0;
            if (cursors[index].m_Locator.m_SampleTable->GetSampleCount()) {
                cursors[index].m_Locator.m_SampleTable->GetSample(0, cursors[index].m_Locator.m_Sample);
            } else {
                cursors[index].m_EndReached = true;
            }

            index++;            
        }

        // figure out the layout of the chunks
        for (;;) {
            // see which is the next sample to write
            AP4_UI64 min_offset = (AP4_UI64)(-1);
            int cursor = -1;
            for (unsigned int i=0; i<track_count; i++) {
                if (!cursors[i].m_EndReached &&
                    cursors[i].m_Locator.m_Sample.GetOffset() <= min_offset) {
                    min_offset = cursors[i].m_Locator.m_Sample.GetOffset();
                    cursor = i;
                }
            }

            // stop if all cursors are exhausted
            if (cursor == -1) break;

            // append this locator to the layout list
            AP4_SampleLocator& locator = cursors[cursor].m_Locator;
            locators.Append(locator);

            // move the cursor to the next sample
            locator.m_SampleIndex++;
            if (locator.m_SampleIndex == locator.m_SampleTable->GetSampleCount()) {
                // mark this track as completed
                cursors[cursor].m_EndReached = true;
            } else {
                // get the next sample info
                locator.m_SampleTable->GetSample(locator.m_SampleIndex, locator.m_Sample);
                AP4_Ordinal skip, sdesc;
                locator.m_SampleTable->GetChunkForSample(locator.m_SampleIndex,
                                                         locator.m_ChunkIndex,
                                                         skip, sdesc);
            }
        }

        // update the stbl atoms and compute the mdat size
        int current_track = -1;
        int current_chunk = -1;
        AP4_Position current_chunk_offset = 0;
        AP4_Size current_chunk_size = 0;
        for (AP4_Ordinal i=0; i<locators.ItemCount(); i++) {
            AP4_SampleLocator& locator = locators[i];
            if ((int)locator.m_TrakIndex  != current_track ||
                (int)locator.m_ChunkIndex != current_chunk) {
                // start a new chunk for this track
                current_chunk_offset += current_chunk_size;
                current_chunk_size = 0;
                current_track = locator.m_TrakIndex;
                current_chunk = locator.m_ChunkIndex;
                locator.m_SampleTable->SetChunkOffset(locator.m_ChunkIndex, current_chunk_offset);
            } 
            AP4_Size sample_size;
            TrackHandler* handler = m_TrackData[locator.m_TrakIndex].track_handler;
            if (handler) {
                sample_size = handler->GetProcessedSampleSize(locator.m_Sample);
                locator.m_SampleTable->SetSampleSize(locator.m_SampleIndex, sample_size);
            } else {
                sample_size = locator.m_Sample.GetSize();
            }
            current_chunk_size += sample_size;
            mdat_payload_size  += sample_size;
        }

        // process the tracks (ex: sample descriptions processing)
        for (AP4_Ordinal i=0; i<track_count; i++) {
            TrackHandler* handler = m_TrackData[i].track_handler;
            if (handler)
				handler->ProcessTrack();
        }
    }

    // finalize the processor
    Finalize(top_level);

    if (!fragments) {
        // calculate the size of all atoms combined
        AP4_UI64 atoms_size = 0;
        top_level.GetChildren().Apply(AP4_AtomSizeAdder(atoms_size));

        // see if we need a 64-bit or 32-bit mdat
        AP4_Size mdat_header_size = AP4_ATOM_HEADER_SIZE;
        if (mdat_payload_size+mdat_header_size > 0xFFFFFFFF) {
            // we need a 64-bit size
            mdat_header_size += 8;
        }
        
        // adjust the chunk offsets
        for (AP4_Ordinal i=0; i<track_count; i++) {
            AP4_TrakAtom* trak;
            trak_atoms->Get(i, trak);
            trak->AdjustChunkOffsets(atoms_size+mdat_header_size);
        }

        // write all atoms
        top_level.GetChildren().Apply(AP4_AtomListWriter(output));

        // write mdat header
        if (mdat_payload_size) {
            if (mdat_header_size == AP4_ATOM_HEADER_SIZE) {
                // 32-bit size
                output.WriteUI32((AP4_UI32)(mdat_header_size+mdat_payload_size));
                output.WriteUI32(AP4_ATOM_TYPE_MDAT);
            } else {
                // 64-bit size
                output.WriteUI32(1);
                output.WriteUI32(AP4_ATOM_TYPE_MDAT);
                output.WriteUI64(mdat_header_size+mdat_payload_size);
            }
        }        
    }
    
    // write the samples
    if (moov) {
        if (!fragments) {
#if defined(AP4_DEBUG)
            AP4_Position before;
            output.Tell(before);
#endif
            AP4_Sample     sample;
            AP4_DataBuffer data_in;
            AP4_DataBuffer data_out;
            for (unsigned int i=0; i<locators.ItemCount(); i++) {
                AP4_SampleLocator& locator = locators[i];
                locator.m_Sample.ReadData(data_in);
                TrackHandler* handler = m_TrackData[locator.m_TrakIndex].track_handler;
                if (handler) {
                    result = handler->ProcessSample(data_in, data_out);
                    if (AP4_FAILED(result)) return result;
                    output.Write(data_out.GetData(), data_out.GetDataSize());
                } else {
                    output.Write(data_in.GetData(), data_in.GetDataSize());            
                }

                // notify the progress listener
                if (listener) {
                    listener->OnProgress(i+1, locators.ItemCount());
                }
            }

#if defined(AP4_DEBUG)
            AP4_Position after;
            output.Tell(after);
            AP4_ASSERT(after-before == mdat_payload_size);
#endif
		}
		else
			m_StreamData[0].stream = fragments;
        
        // find the position of the sidx atom
        AP4_Position sidx_position = 0;
		if (sidx) {
			for (AP4_List<AP4_Atom>::Item* item = top_level.GetChildren().FirstItem();
				item;
				item = item->GetNext()) {
				AP4_Atom* atom = item->GetData();
				if (atom->GetType() == AP4_ATOM_TYPE_SIDX) {
					break;
				}
				sidx_position += atom->GetSize();
			}
		}
        
        // process the fragments, if any
		AP4_Array<AP4_Position> moof_offsets, mdat_offsets;
		moof_offsets.SetItemCount(1);
		mdat_offsets.SetItemCount(1);

		while (frags.ItemCount() > 0)
		{
			for (AP4_List<AP4_AtomLocator>::Item *locator(frags.FirstItem()); locator; locator = locator->GetNext())
			{
				AP4_ContainerAtom *moof(AP4_DYNAMIC_CAST(AP4_ContainerAtom, locator->GetData()->m_Atom));
				moof_offsets[0] = locator->GetData()->m_Offset;
				mdat_offsets[0] = moof_offsets[0] + moof->GetSize() + AP4_ATOM_HEADER_SIZE;

				result = ProcessFragment(moof, sidx, sidx_position, output, moof_offsets, mdat_offsets);
				if (AP4_FAILED(result))
					return result;
			}
			frags.DeleteReferences();

			AP4_Atom* atom = NULL;
			input.Tell(stream_offset);
			if (AP4_SUCCEEDED(atom_factory.CreateAtomFromStream(input, atom)))
			{
				if (atom->GetType() == AP4_ATOM_TYPE_MOOF)
					frags.Add(new AP4_AtomLocator(atom, stream_offset));
				else
					delete atom;
			}
		}

		// update the mfra if we have one
		if (mfra) {
			for (AP4_List<AP4_Atom>::Item* mfra_item = mfra->GetChildren().FirstItem(); mfra_item; mfra_item = mfra_item->GetNext())
			{
				if (mfra_item->GetData()->GetType() != AP4_ATOM_TYPE_TFRA)
					continue;
				AP4_TfraAtom* tfra = AP4_DYNAMIC_CAST(AP4_TfraAtom, mfra_item->GetData());
				if (tfra == NULL)
					continue;
				AP4_Array<AP4_TfraAtom::Entry>& entries = tfra->GetEntries();
				AP4_Cardinal entry_count = entries.ItemCount();
				for (unsigned int i = 0; i<entry_count; i++) {
					entries[i].m_MoofOffset = FindFragmentMapEntry(entries[i].m_MoofOffset);
				}
			}
		}

        // update and re-write the sidx if we have one
        if (sidx && sidx_position) {
            AP4_Position where = 0;
            output.Tell(where);
            output.Seek(sidx_position);
            result = sidx->Write(output);
            if (AP4_FAILED(result)) return result;
            output.Seek(where);
        }
        
        if (!fragments) {
            // write the mfra atom at the end if we have one
            if (mfra) {
                mfra->Write(output);
            }
        }
        
        // cleanup
        for (AP4_Ordinal i=0; i<track_count; i++)
            delete cursors[i].m_Locator.m_SampleTable;
        m_TrackData.Clear();
        delete[] cursors;
    }

    // cleanup
    frags.DeleteReferences();
    delete mfra;
    
    return AP4_SUCCESS;
}
Beispiel #24
0
int ParserEngine::getColumnNumber() const
{
	return locator().getColumnNumber();
}
Beispiel #25
0
void ParserEngine::handleError(int errorNo)
{
	try
	{
		switch (errorNo)
		{
		case XML_ERROR_NO_MEMORY:
			throw XMLException("No memory");
		case XML_ERROR_SYNTAX:
			throw SAXParseException("Syntax error", locator());
		case XML_ERROR_NO_ELEMENTS:
			throw SAXParseException("No element found", locator());
		case XML_ERROR_INVALID_TOKEN:
			throw SAXParseException("Invalid token", locator());
		case XML_ERROR_UNCLOSED_TOKEN:
			throw SAXParseException("Unclosed token", locator());
		case XML_ERROR_PARTIAL_CHAR:
			throw SAXParseException("Partial character", locator());
		case XML_ERROR_TAG_MISMATCH:
			throw SAXParseException("Tag mismatch", locator());
		case XML_ERROR_DUPLICATE_ATTRIBUTE:
			throw SAXParseException("Duplicate attribute", locator());
		case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
			throw SAXParseException("Junk after document element", locator());
		case XML_ERROR_PARAM_ENTITY_REF:
			throw SAXParseException("Illegal parameter entity reference", locator());
		case XML_ERROR_UNDEFINED_ENTITY:
			throw SAXParseException("Undefined entity", locator());
		case XML_ERROR_RECURSIVE_ENTITY_REF:
			throw SAXParseException("Recursive entity reference", locator());
		case XML_ERROR_ASYNC_ENTITY:
			throw SAXParseException("Asynchronous entity", locator());
		case XML_ERROR_BAD_CHAR_REF:
			throw SAXParseException("Reference to invalid character number", locator());
		case XML_ERROR_BINARY_ENTITY_REF:
			throw SAXParseException("Reference to binary entity", locator());
		case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:
			throw SAXParseException("Reference to external entity in attribute", locator());
		case XML_ERROR_MISPLACED_XML_PI:
			throw SAXParseException("XML processing instruction not at start of external entity", locator());
		case XML_ERROR_UNKNOWN_ENCODING:
			throw SAXParseException("Unknown encoding", locator());
		case XML_ERROR_INCORRECT_ENCODING:
			throw SAXParseException("Encoding specified in XML declaration is incorrect", locator());
		case XML_ERROR_UNCLOSED_CDATA_SECTION:
			throw SAXParseException("Unclosed CDATA section", locator());
		case XML_ERROR_EXTERNAL_ENTITY_HANDLING:
			throw SAXParseException("Error in processing external entity reference", locator());
		case XML_ERROR_NOT_STANDALONE:
			throw SAXParseException("Document is not standalone", locator());
		case XML_ERROR_UNEXPECTED_STATE:
			throw SAXParseException("Unexpected parser state - please send a bug report", locator());		
		case XML_ERROR_ENTITY_DECLARED_IN_PE:
			throw SAXParseException("Entity declared in parameter entity", locator());
		case XML_ERROR_FEATURE_REQUIRES_XML_DTD:
			throw SAXParseException("Requested feature requires XML_DTD support in Expat", locator());
		case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING:
			throw SAXParseException("Cannot change setting once parsing has begun", locator());
		case XML_ERROR_UNBOUND_PREFIX:
			throw SAXParseException("Unbound prefix", locator());
		case XML_ERROR_UNDECLARING_PREFIX:
			throw SAXParseException("Must not undeclare prefix", locator());
		case XML_ERROR_INCOMPLETE_PE:
			throw SAXParseException("Incomplete markup in parameter entity", locator());
		case XML_ERROR_XML_DECL:
			throw SAXParseException("XML declaration not well-formed", locator());
		case XML_ERROR_TEXT_DECL:
			throw SAXParseException("Text declaration not well-formed", locator());
		case XML_ERROR_PUBLICID:
			throw SAXParseException("Illegal character(s) in public identifier", locator());
		case XML_ERROR_SUSPENDED:
			throw SAXParseException("Parser suspended", locator());
		case XML_ERROR_NOT_SUSPENDED:
			throw SAXParseException("Parser not suspended", locator());
		case XML_ERROR_ABORTED:
			throw SAXParseException("Parsing aborted", locator());
		case XML_ERROR_FINISHED:
			throw SAXParseException("Parsing finished", locator());
		case XML_ERROR_SUSPEND_PE:
			throw SAXParseException("Cannot suspend in external parameter entity", locator());
		}
		throw XMLException("Unknown Expat error code");
	}
	catch (SAXException& exc)
	{
		if (_pErrorHandler) _pErrorHandler->error(exc);
		throw;
	}
	catch (Poco::Exception& exc)
	{
		if (_pErrorHandler) _pErrorHandler->fatalError(SAXParseException("Fatal error", locator(), exc));
		throw;
	}
}	
Beispiel #26
0
int ParserEngine::getLineNumber() const
{
	return locator().getLineNumber();
}
Beispiel #27
0
XMLString ParserEngine::getSystemId() const
{
	return locator().getSystemId();
}
Beispiel #28
0
XMLString ParserEngine::getPublicId() const
{
	return locator().getPublicId();
}
Beispiel #29
0
int main (int argc, char *argv [])
{
    unicap_handle_t handle;
    unicap_device_t device;
    unicap_format_t src_format;
    unicap_format_t dest_format;
    unicap_data_buffer_t src_buffer;
    unicap_data_buffer_t dest_buffer;
    unicap_data_buffer_t *returned_buffer;

    if (argc != 4) {
        fprintf (stderr, "Usage: sender <hostname> <camera name> "
            "<interface>\n");
        exit (1);
    }

    //  Initialise 0MQ infrastructure

    //  1. Set error handler function (to ignore disconnected receivers)
    zmq::set_error_handler (error_handler);

    //  2. Initialise basic infrastructure for 2 threads
    zmq::dispatcher_t dispatcher (2);

    //  3. Initialise local locator (to connect to global locator)
    zmq::locator_t locator (argv [1]);

    //  4. Start one working thread (to send data to receivers)
    zmq::poll_thread_t *pt = zmq::poll_thread_t::create (&dispatcher);

    //  5. Register one API thread (the application thread - the one that
    //     is being executed at the moment)
    zmq::api_thread_t *api = zmq::api_thread_t::create (&dispatcher, &locator);

    //  6.  Define an entry point for the messages. The name of the entry point
    //      is user-defined ("camera name"). Specify that working thread "pt"
    //      will be used to listen to new connections being created as well as
    //      to send frames to existing connections.
    int e_id = api->create_exchange (argv [2], zmq::scope_global, argv [3],
        pt, 1, &pt);
    
    //  Open first available video capture device
    if (!SUCCESS (unicap_enumerate_devices (NULL, &device, 0))) {
        fprintf (stderr, "Could not enumerate devices\n");
        exit (1);
    }
    if (!SUCCESS (unicap_open (&handle, &device))) {
        fprintf (stderr, "Failed to open device: %s\n", device.identifier);
        exit (1);
    }
    printf( "Opened video capture device: %s\n", device.identifier );

    //  Find a suitable video format that we can convert to RGB24
    bool conversion_found = false;
    int index = 0;
    while (SUCCESS (unicap_enumerate_formats (handle, NULL, &src_format,
          index))) {
        printf ("Trying video format: %s\n", src_format.identifier);
        if (ucil_conversion_supported (FOURCC ('R', 'G', 'B', '3'), 
            src_format.fourcc)) {
            conversion_found = true;
            break;
        }
        index++;
    }
    if (!conversion_found) {
        fprintf (stderr, "Could not find a suitable video format\n");
        exit (1);
    }
    src_format.buffer_type = UNICAP_BUFFER_TYPE_USER;
    if (!SUCCESS (unicap_set_format (handle, &src_format))) {
        fprintf (stderr, "Failed to set video format\n");
        exit (1);
    }
    printf ("Using video format: %s [%dx%d]\n", 
        src_format.identifier, 
        src_format.size.width, 
        src_format.size.height);

    //  Clone destination format with equal dimensions, but RGB24 colorspace
    unicap_copy_format (&dest_format, &src_format);
    strcpy (dest_format.identifier, "RGB 24bpp");
    dest_format.fourcc = FOURCC ('R', 'G', 'B', '3');
    dest_format.bpp = 24;
    dest_format.buffer_size = dest_format.size.width *
        dest_format.size.height * 3;
    
    //  Initialise image buffers
    memset (&src_buffer, 0, sizeof (unicap_data_buffer_t));
    src_buffer.data = (unsigned char *)malloc (src_format.buffer_size);
    src_buffer.buffer_size = src_format.buffer_size;
    memset (&dest_buffer, 0, sizeof (unicap_data_buffer_t));
    dest_buffer.data = (unsigned char *)malloc (dest_format.buffer_size);
    dest_buffer.buffer_size = dest_format.buffer_size;
    dest_buffer.format = dest_format;

    //  Start video capture
    if (!SUCCESS (unicap_start_capture (handle))) {
        fprintf (stderr, "Failed to start capture on device: %s\n",
            device.identifier);
        exit (1);
    }

    //  Loop, sending video to defined exchange
    while (1) {

        //  Queue buffer for video capture
        if (!SUCCESS (unicap_queue_buffer (handle, &src_buffer))) {
            fprintf (stderr, "Failed to queue a buffer on device: %s\n",
                device.identifier);
            exit (1);
        }

        //  Wait until buffer is ready
        if (!SUCCESS (unicap_wait_buffer (handle, &returned_buffer))) {
            fprintf (stderr, "Failed to wait for buffer on device: %s\n",
                device.identifier);
            exit (1);
        }

        //  Convert colorspace
        if (!SUCCESS (ucil_convert_buffer (&dest_buffer, &src_buffer))) {
            //  TODO: This fails sometimes for unknown reasons,
            //  just skip the frame for now
            fprintf (stderr, "Failed to convert video buffer\n");
        }

        //  Create ZMQ message
        zmq::message_t msg (dest_format.buffer_size + (2 * sizeof (uint32_t)));
        unsigned char *data = (unsigned char *)msg.data();

        //  Image width in pixels
        zmq::put_uint32 (data, (uint32_t)dest_format.size.width);
        data += sizeof (uint32_t);

        //  Image height in pixels
        zmq::put_uint32 (data, (uint32_t)dest_format.size.height);
        data += sizeof (uint32_t);

        //  RGB24 image data
        memcpy (data, dest_buffer.data, dest_format.buffer_size);

        //  Send message 
        api->send (e_id, msg);
    }
    
    return 0;
}
AdvDocFile *
AdvData::OpenFile(const std::string &filename)
{
    AdvDocFile *retval = 0;

    if(filename.size() < 1)
        return retval;

    // Look through the advFiles for a match.
    int index = -1;
    int firstEmptySlot = -1;
    for(int i = 0; i < MAX_ADV_FILES; ++i)
    {
        if(advFiles[i] == 0 && firstEmptySlot == -1)
            firstEmptySlot = i;

        if(advFiles[i] != 0)
        {
            // remove the advdoc: string from the front of the filename.
            std::string locator(adv_dio_file_get_locator(advFiles[i]) + 7);
            if(filename == locator)
                index = i;
        }
    }

    if(index == -1)
    {
        // We did not find a match so we need to open the file.
        retval = adv_dio_file_open(filename.c_str(), "r");

        if(retval != 0)
        {
            if(firstEmptySlot == -1)
            {
                // There's no room for the file. Make room by closing the 1st file.
                adv_dio_file_close(advFiles[0]);
                for(int i = 0; i < MAX_ADV_FILES-1; ++i)
                    advFiles[i] = advFiles[i+1];
                advFiles[MAX_ADV_FILES-1] = retval;
            }
            else
            {
                // There's room for the file so cache it.
                advFiles[firstEmptySlot] = retval;
            }
        }
    }
    else
    {
        // We found an existing file in advFiles so let's move it to last in
        // the list.
        retval =  advFiles[index];
        int id = index;
        for(int i = index+1; i < MAX_ADV_FILES; ++i)
        {
            if(advFiles[i] != 0)
                advFiles[id++] = advFiles[i];
        }
        advFiles[id] = retval;
        for(int i = id+1; i < MAX_ADV_FILES; ++i)
            advFiles[i] = 0;
    }

    return retval;
}