std::vector<FacetSequence*> * FacetSequenceTreeBuilder::computeFacetSequences(const Geometry* g) {
    std::unique_ptr<std::vector<FacetSequence*> > sections(new std::vector<FacetSequence*>());

    class FacetSequenceAdder;
    class FacetSequenceAdder : public geom::GeometryComponentFilter {
        std::vector<FacetSequence*>*  m_sections;

    public :
        FacetSequenceAdder(std::vector<FacetSequence*> * p_sections) :
            m_sections(p_sections) {}
        void filter_ro(const Geometry* geom) override {
            if (const LineString* ls = dynamic_cast<const LineString*>(geom)) {
                const CoordinateSequence* seq = ls->getCoordinatesRO();
                addFacetSequences(seq, *m_sections);
            } else if (const Point* pt = dynamic_cast<const Point*>(geom)) {
                const CoordinateSequence* seq = pt->getCoordinatesRO();
                addFacetSequences(seq, *m_sections);
            }
        }
    };

    FacetSequenceAdder facetSequenceAdder(sections.get());
    g->apply_ro(&facetSequenceAdder);

    return sections.release();
}
Exemple #2
0
std::vector<Section> File::findSections(const util::Filter<Section>::type &filter, size_t max_depth) const {
    std::vector<Section> results;
    std::vector<Section> roots = sections();
    for (auto root : roots) {
        std::vector<Section> secs = root.findSections(filter, max_depth);
        results.insert(results.end(), secs.begin(), secs.end());
    }
    return results;
}
STRtree* FacetSequenceTreeBuilder::build(const Geometry* g) {
    std::unique_ptr<STRtree> tree(new STRtree(STR_TREE_NODE_CAPACITY));
    std::unique_ptr<std::vector<FacetSequence*> > sections(computeFacetSequences(g));
    for (std::vector<FacetSequence*>::iterator it = sections->begin(); it != sections->end(); ++it) {
        FacetSequence* section = *it;
        tree->insert(section->getEnvelope(), section);
    }

    tree->build();
    return tree.release();
}
Exemple #4
0
void DumpSections(hadesmem::Process const& process,
                  hadesmem::PeFile const& pe_file)
{
  hadesmem::SectionList sections(process, pe_file);

  std::wostream& out = GetOutputStreamW();

  if (std::begin(sections) != std::end(sections))
  {
    WriteNewline(out);
    WriteNormal(out, L"Sections:", 1);
  }
  else
  {
    // Other checks on number of sections are done as part of header handling.
    hadesmem::NtHeaders const nt_hdrs(process, pe_file);
    if (nt_hdrs.GetNumberOfSections())
    {
      WriteNewline(out);
      WriteNormal(out, L"WARNING! Section list is inavlid.", 1);
      WarnForCurrentFile(WarningType::kUnsupported);
    }
  }

  for (auto const& s : sections)
  {
    WriteNewline(out);
    if (s.IsVirtual())
    {
      WriteNormal(out, L"WARNING! Section is virtual.", 2);
      WarnForCurrentFile(WarningType::kSuspicious);
    }
    HandleLongOrUnprintableString(
      L"name", L"section name", 2, WarningType::kSuspicious, s.GetName());
    WriteNamedHex(out, L"VirtualAddress", s.GetVirtualAddress(), 2);
    WriteNamedHex(out, L"VirtualSize", s.GetVirtualSize(), 2);
    WriteNamedHex(out, L"PointerToRawData", s.GetPointerToRawData(), 2);
    WriteNamedHex(out, L"SizeOfRawData", s.GetSizeOfRawData(), 2);
    WriteNamedHex(out, L"PointerToRelocations", s.GetPointerToRelocations(), 2);
    WriteNamedHex(out, L"PointerToLinenumbers", s.GetPointerToLinenumbers(), 2);
    WriteNamedHex(out, L"NumberOfRelocations", s.GetNumberOfRelocations(), 2);
    WriteNamedHex(out, L"NumberOfLinenumbers", s.GetNumberOfLinenumbers(), 2);
    WriteNamedHex(out, L"Characteristics", s.GetCharacteristics(), 2);
  }
}
Exemple #5
0
void Donations::loadSectionDonations() {
	QSqlQuery query = createDonationsQuery();
	query.exec();
	donationsModel->setQuery(query);
	
	donationsModel->setHeaderData(0, Qt::Horizontal, tr("Person"));
	donationsModel->setHeaderData(1, Qt::Horizontal, tr("Amount"));
	donationsModel->setHeaderData(2, Qt::Horizontal, tr("City"));
	donationsModel->setHeaderData(3, Qt::Horizontal, tr("Section"));
	donationsModel->setHeaderData(4, Qt::Horizontal, tr("Date"));
	donationsModel->setHeaderData(5, Qt::Horizontal, tr("Objective"));
	
	donationsTable->setSortingEnabled(false);
	donationsTable->setModel(donationsModel);
	
	QSqlQuery sections(db);
	sections.prepare("SELECT section FROM donation_entities GROUP BY section ORDER BY section ASC;");
	sections.exec();
	sectionList->addItem(tr("all"));
	while (sections.next()) {
		sectionList->addItem(sections.value(0).toString());
	}
}
Exemple #6
0
grade_template::grade_template(QString lesson_name, QSqlDatabase &db, osman *parent) :
    QWidget(parent),
    ui(new Ui::grade_template)
{
    this->db = db;
    this->lesson_name = lesson_name;
    this->parent=parent;
    ui->setupUi(this);
    sec = sections();
    QStringList sections = sec.getSections(lesson_name);
    if(sections.isEmpty())
        return;

    ui->comboBox_section->clear();
    ui->comboBox_section->addItems(sections);
    ui->tabWidget->removeTab(0);
    for(int index = 0; index < sections.count(); index++)
    {
        ui->tabWidget->addTab(new section_template(sections.at(index), db, this), sections.at(index));
        /*
          This loop adding tabs using section_template.
        */
    }
}
Exemple #7
0
void	CGLMProgram::SetProgramText( char *text )
{
	// free old text if any
	// clone new text
	// scan newtext to find sections
	// walk sections, and mark descs to indicate where text is at
	
	if (m_text)
	{
		free( m_text );
		m_text = NULL;
	}
	
	// scrub desc text references
	for( int i=0; i<kGLMNumProgramTypes; i++)
	{
		GLMShaderDesc	*desc = &m_descs[i];
		
		desc->m_textPresent = false;
		desc->m_textOffset	= 0;
		desc->m_textLength	= 0;
	}
	
	m_text = strdup( text );
	Assert( m_text != NULL );	

	#if GLMDEBUG
		// create editable text item, if it does not already exist
		if (!m_editable)
		{
			char	*suffix = "";

			switch(m_type)
			{
				case	kGLMVertexProgram:		suffix = ".vsh"; break;
				case	kGLMFragmentProgram:	suffix = ".fsh"; break;
				default:	GLMDebugger();
			}

#ifdef POSIX
            CFmtStr debugShaderPath( "%s/debugshaders/", getenv( "HOME" ) );
#else
			CFmtStr debugShaderPath( "debugshaders/" );
#endif
			_mkdir( debugShaderPath.Access() );
			m_editable = new CGLMEditableTextItem( m_text, strlen(m_text), false, debugShaderPath.Access(), suffix );
			
			// pull our string back from the editable (it has probably munged it)
			if (m_editable->HasData())
			{
				ReloadStringFromEditable();
			}
		}
	#endif

	
	// scan the text and find sections
	CGLMTextSectioner		sections( m_text, strlen( m_text ), g_shaderSectionMarkers );
	
	int sectionCount = sections.Count();
	for( int i=0; i < sectionCount; i++ )
	{
		uint subtextOffset	= 0;
		uint subtextLength	= 0;
		int markerIndex		= 0;
		
		sections.GetSection( i, &subtextOffset, &subtextLength, &markerIndex );

		// act on the section
		GLMShaderDesc *desc = NULL;
		switch( m_type )
		{
			case kGLMVertexProgram:
				switch( markerIndex )
				{
					case	kGLMARBVertex:
					case	kGLMGLSLVertex:
						desc = &m_descs[ (markerIndex==kGLMARBVertex) ? kGLMARB : kGLMGLSL];

						// these steps are generic across both langs
						desc->m_textPresent	= true;
						desc->m_textOffset	= subtextOffset;
						desc->m_textLength	= subtextLength;
						desc->m_compiled	= false;
						desc->m_valid		= false;
					break;

					case	kGLMARBVertexDisabled:
					case	kGLMGLSLVertexDisabled:
						// ignore quietly
					break;
					
					default: Assert(!"Mismatched section marker seen in SetProgramText (VP)"); break;
				}
			break;
			
			case kGLMFragmentProgram:
				switch( markerIndex )
				{
					case	kGLMARBFragment:
					case	kGLMGLSLFragment:
						desc = &m_descs[ (markerIndex==kGLMARBFragment) ? kGLMARB : kGLMGLSL];

						// these steps are generic across both langs
						desc->m_textPresent	= true;
						desc->m_textOffset	= subtextOffset;
						desc->m_textLength	= subtextLength;
						desc->m_compiled	= false;
						desc->m_valid		= false;
					break;

					case	kGLMARBFragmentDisabled:
					case	kGLMGLSLFragmentDisabled:
						// ignore quietly
					break;
					
					default: Assert(!"Mismatched section marker seen in SetProgramText (VP)"); break;
				}
			break;			
		}
	}
}
Exemple #8
0
// Mark all line differences
bool showDiffs(HWND view1, HWND view2, const std::pair<std::vector<diff_info>, bool>& cmpResults,
		progress_ptr& progress)
{
	const std::vector<diff_info>& blockDiff = cmpResults.first;

	const diff_mark deletedMark	= cmpResults.second ? ADDED_MARK : DELETED_MARK;
	const diff_mark addedMark	= cmpResults.second ? DELETED_MARK : ADDED_MARK;

	const int blockDiffSize = static_cast<int>(blockDiff.size());

	if (progress)
		progress->SetMaxCount(blockDiffSize);

	int addedBlanks1 = 0;
	int addedBlanks2 = 0;

	for (int i = 0; i < blockDiffSize; ++i)
	{
		const diff_info& bd = blockDiff[i];

		if (bd.type != diff_type::DIFF_MATCH)
		{
			std::pair<HWND, HWND> views;
			std::pair<int*, int*> addedBlanks;
			std::pair<diff_mark, diff_mark> bdMarks;

			if (bd.type == diff_type::DIFF_DELETE)
			{
				addedBlanks.first	= &addedBlanks1;
				addedBlanks.second	= &addedBlanks2;
				views.first			= view1;
				views.second		= view2;
				bdMarks.first		= deletedMark;
				bdMarks.second		= addedMark;
			}
			else // diff_type::DIFF_INSERT
			{
				addedBlanks.first	= &addedBlanks2;
				addedBlanks.second	= &addedBlanks1;
				views.first			= view2;
				views.second		= view1;
				bdMarks.first		= addedMark;
				bdMarks.second		= deletedMark;
			}

			std::pair<section_t, section_t> sections( {0, 0}, {0, 0} );

			const int changedLinesCount = static_cast<int>(bd.changedLines.size());

			for (int j = 0; j < changedLinesCount; ++j)
			{
				const std::pair<const diff_line&, const diff_line&>
						changedLines( bd.changedLines[j], bd.matchedDiff->changedLines[j] );

				if (sections.first.off != changedLines.first.line ||
					sections.second.off != changedLines.second.line)
				{
					sections.first.len = changedLines.first.line - sections.first.off;
					sections.second.len = changedLines.second.line - sections.second.off;

					markSection(views, bd, bdMarks, sections, addedBlanks);
				}

				markLineDiffs(views, changedLines, bd.off + *addedBlanks.first + changedLines.first.line);

				sections.first.off = changedLines.first.line + 1;
				sections.second.off = changedLines.second.line + 1;
			}

			sections.first.len = bd.len - sections.first.off;

			if (bd.matchedDiff)
			{
				sections.second.len = bd.matchedDiff->len - sections.second.off;
				++i;
			}
			else
			{
				sections.second.len = 0;
			}

			markSection(views, bd, bdMarks, sections, addedBlanks);
		}

		if (progress && !progress->Advance())
			return false;
	}

	if (progress && !progress->NextPhase())
		return false;

	return true;
}
Exemple #9
0
void TestSectionList()
{
  hadesmem::Process const process(::GetCurrentProcessId());

  hadesmem::PeFile pe_file_1(
    process, ::GetModuleHandleW(nullptr), hadesmem::PeFileType::Image, 0);

  hadesmem::NtHeaders nt_headers_1(process, pe_file_1);

  BOOST_TEST(nt_headers_1.GetNumberOfSections() >= 1);

  hadesmem::Section section_1(process, pe_file_1, 0);

  hadesmem::Section section_2(section_1);
  BOOST_TEST_EQ(section_1, section_2);
  section_1 = section_2;
  BOOST_TEST_EQ(section_1, section_2);
  hadesmem::Section section_3(std::move(section_2));
  BOOST_TEST_EQ(section_3, section_1);
  section_2 = std::move(section_3);
  BOOST_TEST_EQ(section_1, section_2);

  hadesmem::ModuleList modules(process);
  for (auto const& mod : modules)
  {
    hadesmem::PeFile const pe_file(
      process, mod.GetHandle(), hadesmem::PeFileType::Image, 0);

    hadesmem::NtHeaders const nt_headers(process, pe_file);
    WORD const num_sections = nt_headers.GetNumberOfSections();

    // Assume every module has at least one section.
    hadesmem::SectionList sections(process, pe_file);
    WORD section_count = 0;
    for (auto& section : sections)
    {
      section_count = static_cast<WORD>(section_count + 1);

      auto const section_header_raw =
        hadesmem::Read<IMAGE_SECTION_HEADER>(process, section.GetBase());

      section.SetName(section.GetName());
      section.SetVirtualAddress(section.GetVirtualAddress());
      section.SetVirtualSize(section.GetVirtualSize());
      section.SetSizeOfRawData(section.GetSizeOfRawData());
      section.SetPointerToRawData(section.GetPointerToRawData());
      section.SetPointerToRelocations(section.GetPointerToRelocations());
      section.SetPointerToLinenumbers(section.GetPointerToLinenumbers());
      section.SetNumberOfRelocations(section.GetNumberOfRelocations());
      section.SetNumberOfLinenumbers(section.GetNumberOfLinenumbers());
      section.SetCharacteristics(section.GetCharacteristics());
      section.UpdateWrite();
      section.UpdateRead();

      auto const section_header_raw_new =
        hadesmem::Read<IMAGE_SECTION_HEADER>(process, section.GetBase());

      BOOST_TEST_EQ(std::memcmp(&section_header_raw,
                                &section_header_raw_new,
                                sizeof(section_header_raw)),
                    0);

      std::stringstream test_str_1;
      test_str_1.imbue(std::locale::classic());
      test_str_1 << section;
      std::stringstream test_str_2;
      test_str_2.imbue(std::locale::classic());
      test_str_2 << section.GetBase();
      BOOST_TEST_EQ(test_str_1.str(), test_str_2.str());
      if (mod.GetHandle() != GetModuleHandle(L"ntdll"))
      {
        hadesmem::PeFile const pe_file_ntdll(process,
                                             ::GetModuleHandleW(L"ntdll"),
                                             hadesmem::PeFileType::Image,
                                             0);
        hadesmem::Section const section_ntdll(process, pe_file_ntdll, 0);
        std::stringstream test_str_3;
        test_str_3.imbue(std::locale::classic());
        test_str_3 << section_ntdll.GetBase();
        BOOST_TEST_NE(test_str_1.str(), test_str_3.str());
      }
    }
    BOOST_TEST(section_count == num_sections);

    // Assume every module has a '.text' section.
    auto text_iter = std::find_if(std::begin(sections),
                                  std::end(sections),
                                  [](hadesmem::Section const& section)
                                  {
      return section.GetName() == ".data";
    });
    BOOST_TEST(text_iter != std::end(sections));
  }
}
int main (int argc, char *argv[])
{
    std::vector<cv::Point2i> calibration_points;
    calibration_points.push_back(cv::Point2i(0, 0));
    calibration_points.push_back(cv::Point2i(W/2, 0));
    calibration_points.push_back(cv::Point2i(W-1, 0));
    calibration_points.push_back(cv::Point2i(W-1, H/2));
    calibration_points.push_back(cv::Point2i(W-1, H-1));
    calibration_points.push_back(cv::Point2i(W/2, H-1));
    calibration_points.push_back(cv::Point2i(0, H-1));
    calibration_points.push_back(cv::Point2i(0, H/2));
    calibration_points.push_back(cv::Point2i(W/2, H/2));


    srand( time(NULL) );
    cv::VideoCapture cap;
    std::string auth_key;
    std::string file_name;
    std::string data_dir = "../data/";
    std::string input;
    bool is_capturing = false;
    switch (argc)
    {
        case 4:
        {
            file_name = argv[1];
            data_dir  = argv[2];
            auth_key = argv[3];
            input = argv[1];
            cap.open(file_name);
            break;
        }
        case 5:
        {
            file_name = argv[1];
            if (file_name.find("--capture") != std::string::npos)
            {
                cap.open(atoi(argv[2]));
                is_capturing = true;
                file_name = std::string("capture-") + argv[2] + ".csv";
                input = argv[2];
            }
            data_dir = argv[3];
            auth_key = argv[4];
            break;
        }
        default:
        {

#ifdef HARDCODED_PARAMS
        cap.open(0);
        is_capturing = true;
  #ifdef __APPLE__
            
        //get path to Resource directory in OSX app bundle
        CFBundleRef mainBundle;
        mainBundle = CFBundleGetMainBundle();
        CFURLRef resourceURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
        CFURLRef dataURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
                                 resourceURL,
                                   CFSTR("data"),
                                   true);
        char buffer[1024];
        if(CFURLGetFileSystemRepresentation(dataURL, true, (UInt8*)buffer, 1024)) {
            //TODO: fix trailing slash not being appended automatically
            data_dir = std::string(buffer) + "/";
        }
             
  #else
        //same place as executable
        data_dir = "./data/";
  #endif
        auth_key = "medusa123";
#else
         std::cout
         << "Usage: "
         << argv[0]
         << " <videofile> <data dir> <auth key>"
         << std::endl;
         std::cout
         << "       "
         << argv[0]
         << " --capture <camera-id> <data dir> <auth key>"
         << std::endl;
         return -1;
#endif
        }
    }

    if(!cap.isOpened())  // check if we can capture from camera
    {
    	std::cerr 
            << "Couldn't capture video from input "
            << input
            << std::endl;
    	return -1;
    }
    
    cap.set(CV_CAP_PROP_FRAME_WIDTH,
			InSight::getCamWidthRes());
    cap.set(CV_CAP_PROP_FRAME_HEIGHT,
			InSight::getCamHeightRes());
    
    InSight insight(data_dir);
    if(!insight.authenticate(auth_key))
    {
    	std::cerr << insight.getError() << std::endl;
    	return -1;
    }
    
    cv::namedWindow(HUMAN_NAME, CV_WINDOW_NORMAL);
    cv::setWindowProperty(HUMAN_NAME, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
    // Initialize gaze-grid
    cv::Mat camera, view, temp;
	int pixel_width = InSight::getScreenWidthRes(),
        pixel_height = InSight::getScreenHeightRes();
    view.create(cv::Size(pixel_width, pixel_height), CV_8UC3);
    view.setTo(cv::Scalar(0,0,0));
    cv::Rect roi(pixel_width-CAMVIEW_WIDTH,0,CAMVIEW_WIDTH,CAMVIEW_HEIGHT);
    std::vector<cv::Rect> sections(W*H);
    float width = pixel_width/float(W);
    float height = pixel_height/float(H);
    for (int i = 0; i < H; i++)
    {
        for (int j = 0; j < W; j++)
        {
            sections[i*W+j] =
                    cv::Rect(j*width+BORDER,i*height+BORDER,width-BORDER,height-BORDER);
            temp = view(sections[i*W+j]);
            temp.setTo(cv::Scalar(255,255,255));
        }
    }
    cv::Point2i prev_head_gaze(0);
    cv::Point2i prev_eye_gaze(0);
    int time = 0;
    int timer = 0;
    unsigned int num_point = 0;
    FSM state = ERASE;
    cv::Point2i calib_point(0);
    bool is_ready = false;
    // Start indefinite loop and track eye gaze
    for(;;)
    {
        cap >> camera;

        if (is_capturing)
        {
            cv::flip(camera, camera, 1);
        }

        if (is_ready)
        {
            if (!insight.isInit())
            {
                if(!insight.init(camera))
                {
                    std::cerr << insight.getError() << std::endl;
                }
                cvMoveWindow(HUMAN_NAME,0,0);
            }
            else
            {
                if(!insight.process(camera))
                {
                    std::cerr << insight.getError() << std::endl;
                }
                else
                {
                    if (num_point < calibration_points.size())
                    {
                        switch (state)
                        {
                        case ERASE: {
                            drawPoint(view, calib_point, cv::Scalar(255,255,255));
                            state = DRAW;
                        } break;
                        case DRAW: {
                            calib_point.x = calibration_points[num_point].x * width + width/2;
                            calib_point.y = calibration_points[num_point].y * height + height/2;
                            drawPoint(view, calib_point, cv::Scalar(0,0,255));
                            timer = time + 10;
                            state = IDLE;
                        } break;
                        case IDLE: {
                            if (time > timer)
                            {
                                state = ADD;
                                timer = time + 2;
                            }
                        } break;
                        case ADD: {
                            if (time < timer)
                                insight.addCalibrationPoint(calib_point);
                            else
                            {
                                state = ERASE;
                                num_point++;
                            }
                        } break;
                        default: return -1;
                        }
                        if (num_point == calibration_points.size())
                            insight.calibrate();
                    }
                    else
                    {
                        cv::Point2i head_gaze, eye_gaze;
                        if (insight.getHeadGaze(head_gaze))
                        {
                            head_gaze = cv::Point2i(head_gaze.x / width, head_gaze.y / height);
                            if (prev_head_gaze != head_gaze)
                            {
                                temp = view(sections[prev_head_gaze.y*W+prev_head_gaze.x]);
                                temp.setTo(cv::Scalar(255,255,255));
                            }
                            temp = view(sections.at(head_gaze.y*W+head_gaze.x));
                            temp.setTo(cv::Scalar(255,0,0));
                            prev_head_gaze = head_gaze;
                        }
                        if (insight.getEyeGaze(eye_gaze))
                        {
                            eye_gaze = cv::Point2i(eye_gaze.x / width, eye_gaze.y / height);
                            if (prev_eye_gaze != eye_gaze && prev_eye_gaze != head_gaze)
                            {
                                temp = view(sections[prev_eye_gaze.y*W+prev_eye_gaze.x]);
                                temp.setTo(cv::Scalar(255,255,255));
                            }

                            temp = view(sections.at(eye_gaze.y*W+eye_gaze.x));
                            cv::Scalar color(0,0,255);
                            if (eye_gaze == head_gaze)
                            {
                                color = cv::Scalar(128,0,128);
                            }
                            temp.setTo(color);
                            prev_eye_gaze = eye_gaze;
                        }
                        insight.drawWireFace(camera);
                        cv::resize(camera, temp, cv::Size(CAMVIEW_WIDTH,CAMVIEW_HEIGHT));
                        camera = view(roi);
                        temp.copyTo(camera);
                    }
                }
            }
        }
        imshow(HUMAN_NAME, view);
        char key = cv::waitKey(1);
        switch (key)
        {
        case 'q': return 0;
        case 's': is_ready = true; break;
        default: break;
        }
        time++;
    }
    return 0;
}
Exemple #11
0
static void DeserializeAdvancedSettings(const WCHAR *filepath, SettingInfo *info, size_t count, void *structBase)
{
    char *base = (char *)structBase;
    const WCHAR *section = NULL;
    INT intValue, intValueDef;
    ScopedMem<WCHAR> strValue;

    for (size_t i = 0; i < count; i++) {
        SettingInfo& meta = info[i];
        CrashIf(meta.type != SType_Section && !section);
        switch (meta.type) {
        case SType_Section:
            section = meta.name;
            break;
        case SType_Bool:
            intValueDef = *(bool *)(base + meta.offset) ? 1 : 0;
            intValue = GetPrivateProfileInt(section, meta.name, intValueDef, filepath);
            *(bool *)(base + meta.offset) = intValue != 0;
            break;
        case SType_Color:
            strValue.Set(ReadIniString(filepath, section, meta.name));
            if (str::Parse(strValue, L"#%6x", &intValue))
                *(COLORREF *)(base + meta.offset) = (COLORREF)intValue;
            break;
        case SType_Int:
            intValueDef = *(int *)(base + meta.offset);
            intValue = GetPrivateProfileInt(section, meta.name, intValueDef, filepath);
            *(int *)(base + meta.offset) = intValue;
            break;
        case SType_String:
            strValue.Set(ReadIniString(filepath, section, meta.name, L"\n"));
            if (!str::Eq(strValue, L"\n"))
                ((ScopedMem<WCHAR> *)(base + meta.offset))->Set(strValue.StealData());
            break;
        case SType_BoolVec:
        case SType_ColorVec:
        case SType_IntVec:
        case SType_StringVec:
            ScopedMem<WCHAR> sections(ReadIniString(filepath, section, NULL));
            for (const WCHAR *name = sections; *name; name += str::Len(name) + 1) {
                UINT idx;
                if (str::Eq(str::Parse(name, L"%u.", &idx), meta.name)) {
                    if (SType_BoolVec == meta.type) {
                        bool value = GetPrivateProfileInt(section, name, 0, filepath) != 0;
                        ((Vec<bool> *)(base + meta.offset))->InsertAt(idx, value);
                    }
                    else if (SType_ColorVec == meta.type) {
                        strValue.Set(ReadIniString(filepath, section, name));
                        if (str::Parse(strValue, L"#%6x", &intValue)) {
                            COLORREF value = (COLORREF)intValue;
                            ((Vec<COLORREF> *)(base + meta.offset))->InsertAt(idx, value);
                        }
                    }
                    else if (SType_IntVec == meta.type) {
                        intValue = GetPrivateProfileInt(section, name, 0, filepath);
                        ((Vec<int> *)(base + meta.offset))->InsertAt(idx, intValue);
                    }
                    else {
                        strValue.Set(ReadIniString(filepath, section, name));
                        WStrVec *strVec = (WStrVec *)(base + meta.offset);
                        // TODO: shouldn't InsertAt free the previous string?
                        if (idx < strVec->Count())
                            free(strVec->At(idx));
                        strVec->InsertAt(idx, strValue.StealData());
                    }
                }
            }
            break;
        }
    }
}