Show:
  1. #include "gdal_common.hpp"
  2. #include "gdal_majorobject.hpp"
  3. #include "gdal_driver.hpp"
  4. #include "gdal_dataset.hpp"
  5. #include "utils/string_list.hpp"
  6.  
  7. namespace node_gdal {
  8.  
  9. Nan::Persistent<FunctionTemplate> Driver::constructor;
  10. ObjectCache<GDALDriver, Driver> Driver::cache;
  11. #if GDAL_VERSION_MAJOR < 2
  12. ObjectCache<OGRSFDriver, Driver> Driver::cache_ogr;
  13. #endif
  14.  
  15. void Driver::Initialize(Local<Object> target)
  16. {
  17. Nan::HandleScope scope;
  18.  
  19. Local<FunctionTemplate> lcons = Nan::New<FunctionTemplate>(Driver::New);
  20. lcons->InstanceTemplate()->SetInternalFieldCount(1);
  21. lcons->SetClassName(Nan::New("Driver").ToLocalChecked());
  22.  
  23. Nan::SetPrototypeMethod(lcons, "toString", toString);
  24. Nan::SetPrototypeMethod(lcons, "open", open);
  25. Nan::SetPrototypeMethod(lcons, "create", create);
  26. Nan::SetPrototypeMethod(lcons, "createCopy", createCopy);
  27. Nan::SetPrototypeMethod(lcons, "deleteDataset", deleteDataset);
  28. Nan::SetPrototypeMethod(lcons, "rename", rename);
  29. Nan::SetPrototypeMethod(lcons, "copyFiles", copyFiles);
  30. Nan::SetPrototypeMethod(lcons, "getMetadata", getMetadata);
  31.  
  32. ATTR(lcons, "description", descriptionGetter, READ_ONLY_SETTER);
  33.  
  34. Nan::Set(target, Nan::New("Driver").ToLocalChecked(), Nan::GetFunction(lcons).ToLocalChecked());
  35.  
  36. constructor.Reset(lcons);
  37. }
  38.  
  39.  
  40. #if GDAL_VERSION_MAJOR < 2
  41. Driver::Driver(GDALDriver *driver)
  42. : Nan::ObjectWrap(), uses_ogr(false), this_gdaldriver(driver), this_ogrdriver(0)
  43. {
  44. LOG("Created GDAL Driver [%p]", driver);
  45. }
  46. Driver::Driver(OGRSFDriver *driver)
  47. : Nan::ObjectWrap(), uses_ogr(true), this_gdaldriver(0), this_ogrdriver(driver)
  48. {
  49. LOG("Created OGR Driver [%p]", driver);
  50. }
  51. Driver::Driver()
  52. : Nan::ObjectWrap(), uses_ogr(false), this_gdaldriver(0), this_ogrdriver(0)
  53. {
  54. }
  55. #else
  56. Driver::Driver(GDALDriver *driver)
  57. : Nan::ObjectWrap(), this_gdaldriver(driver)
  58. {
  59. LOG("Created GDAL Driver [%p]", driver);
  60. }
  61. Driver::Driver()
  62. : Nan::ObjectWrap(), this_gdaldriver(0)
  63. {
  64. }
  65. #endif
  66.  
  67.  
  68.  
  69. Driver::~Driver()
  70. {
  71. dispose();
  72. }
  73.  
  74. void Driver::dispose()
  75. {
  76. #if GDAL_VERSION_MAJOR < 2
  77. if(uses_ogr) {
  78. if(this_ogrdriver) {
  79. LOG("Disposing OGR Driver [%p]", this_ogrdriver);
  80. cache_ogr.erase(this_ogrdriver);
  81. LOG("Disposed OGR Driver [%p]", this_ogrdriver);
  82. this_ogrdriver = NULL;
  83. }
  84. return;
  85. }
  86. #endif
  87. if(this_gdaldriver) {
  88. LOG("Disposing GDAL Driver [%p]", this_gdaldriver);
  89. cache.erase(this_gdaldriver);
  90. LOG("Disposed GDAL Driver [%p]", this_gdaldriver);
  91. this_gdaldriver = NULL;
  92. }
  93. }
  94.  
  95.  
  96. /**
  97. * Format specific driver.
  98. *
  99. * An instance of this class is created for each supported format, and
  100. * manages information about the format.
  101. *
  102. * This roughly corresponds to a file format, though some drivers may
  103. * be gateways to many formats through a secondary multi-library.
  104. *
  105. * @class gdal.Driver
  106. */
  107. NAN_METHOD(Driver::New)
  108. {
  109. Nan::HandleScope scope;
  110.  
  111. if (!info.IsConstructCall()) {
  112. Nan::ThrowError("Cannot call constructor as function, you need to use 'new' keyword");
  113. return;
  114. }
  115.  
  116. if (info[0]->IsExternal()) {
  117. Local<External> ext = info[0].As<External>();
  118. void* ptr = ext->Value();
  119. Driver *f = static_cast<Driver *>(ptr);
  120. f->Wrap(info.This());
  121.  
  122. info.GetReturnValue().Set(info.This());
  123. return;
  124. } else {
  125. Nan::ThrowError("Cannot create Driver directly");
  126. return;
  127. }
  128. }
  129.  
  130. Local<Value> Driver::New(GDALDriver *driver)
  131. {
  132. Nan::EscapableHandleScope scope;
  133.  
  134. if (!driver) {
  135. return scope.Escape(Nan::Null());
  136. }
  137. if (cache.has(driver)) {
  138. return scope.Escape(cache.get(driver));
  139. }
  140.  
  141. Driver *wrapped = new Driver(driver);
  142. Local<Value> ext = Nan::New<External>(wrapped);
  143. Local<Object> obj = Nan::NewInstance(Nan::GetFunction(Nan::New(Driver::constructor)).ToLocalChecked(), 1, &ext).ToLocalChecked();
  144.  
  145. //LOG("ADDING DRIVER TO CACHE [%p]", driver);
  146. cache.add(driver, obj);
  147. //LOG("DONE ADDING DRIVER TO CACHE [%p]", driver);
  148.  
  149. return scope.Escape(obj);
  150. }
  151.  
  152. #if GDAL_VERSION_MAJOR < 2
  153. Local<Value> Driver::New(OGRSFDriver *driver)
  154. {
  155. Nan::EscapableHandleScope scope;
  156.  
  157. if (!driver) {
  158. return scope.Escape(Nan::Null());
  159. }
  160. if (cache_ogr.has(driver)) {
  161. return scope.Escape(cache_ogr.get(driver));
  162. }
  163.  
  164. Driver *wrapped = new Driver(driver);
  165. Local<Value> ext = Nan::New<External>(wrapped);
  166. v8::Local<v8::Object> obj = Nan::NewInstance(Nan::GetFunction(Nan::New(Driver::constructor)).ToLocalChecked(), 1, &ext).ToLocalChecked();
  167.  
  168. cache_ogr.add(driver, obj);
  169.  
  170. return scope.Escape(obj);
  171. }
  172. #endif
  173.  
  174. NAN_METHOD(Driver::toString)
  175. {
  176. Nan::HandleScope scope;
  177. info.GetReturnValue().Set(Nan::New("Driver").ToLocalChecked());
  178. }
  179.  
  180. /**
  181. * @readOnly
  182. * @attribute description
  183. * @type String
  184. */
  185. NAN_GETTER(Driver::descriptionGetter)
  186. {
  187. Nan::HandleScope scope;
  188. Driver* driver = Nan::ObjectWrap::Unwrap<Driver>(info.This());
  189.  
  190. #if GDAL_VERSION_MAJOR < 2
  191. if (driver->uses_ogr) {
  192. info.GetReturnValue().Set(SafeString::New(driver->getOGRSFDriver()->GetName()));
  193. return;
  194. }
  195. #endif
  196.  
  197. info.GetReturnValue().Set(SafeString::New(driver->getGDALDriver()->GetDescription()));
  198. }
  199.  
  200. /**
  201. * @throws Error
  202. * @method deleteDataset
  203. * @param {string} filename
  204. */
  205. NAN_METHOD(Driver::deleteDataset)
  206. {
  207. Nan::HandleScope scope;
  208.  
  209. std::string name("");
  210. NODE_ARG_STR(0, "dataset name", name);
  211.  
  212. Driver* driver = Nan::ObjectWrap::Unwrap<Driver>(info.This());
  213.  
  214. #if GDAL_VERSION_MAJOR < 2
  215. if (driver->uses_ogr) {
  216. OGRErr err = driver->getOGRSFDriver()->DeleteDataSource(name.c_str());
  217. if(err) {
  218. NODE_THROW_OGRERR(err);
  219. return;
  220. }
  221. return;
  222. }
  223. #endif
  224.  
  225. CPLErr err = driver->getGDALDriver()->Delete(name.c_str());
  226. if (err) {
  227. NODE_THROW_CPLERR(err);
  228. return;
  229. }
  230. return;
  231. }
  232.  
  233. /**
  234. * Create a new dataset with this driver.
  235. *
  236. * @throws Error
  237. * @method create
  238. * @param {String} filename
  239. * @param {Integer} [x_size=0] raster width in pixels (ignored for vector datasets)
  240. * @param {Integer} [y_size=0] raster height in pixels (ignored for vector datasets)
  241. * @param {Integer} [band_count=0]
  242. * @param {Integer} [data_type=gdal.GDT_Byte] pixel data type (ignored for vector datasets) (see {{#crossLink "Constants (GDT)"}}data types{{/crossLink}})
  243. * @param {String[]|object} [creation_options] An array or object containing driver-specific dataset creation options
  244. * @return gdal.Dataset
  245. */
  246. NAN_METHOD(Driver::create)
  247. {
  248. Nan::HandleScope scope;
  249. Driver *driver = Nan::ObjectWrap::Unwrap<Driver>(info.This());
  250.  
  251. std::string filename;
  252. unsigned int x_size = 0, y_size = 0, n_bands = 0;
  253. GDALDataType type = GDT_Byte;
  254. std::string type_name = "";
  255. StringList options;
  256.  
  257. NODE_ARG_STR(0, "filename", filename);
  258.  
  259. if(info.Length() < 3){
  260. if(info.Length() > 1 && options.parse(info[1])){
  261. return; //error parsing string list
  262. }
  263. } else {
  264. NODE_ARG_INT(1, "x size", x_size);
  265. NODE_ARG_INT(2, "y size", y_size);
  266. NODE_ARG_INT_OPT(3, "number of bands", n_bands);
  267. NODE_ARG_OPT_STR(4, "data type", type_name);
  268. if(info.Length() > 5 && options.parse(info[5])){
  269. return; //error parsing string list
  270. }
  271. if(!type_name.empty()) {
  272. type = GDALGetDataTypeByName(type_name.c_str());
  273. }
  274. }
  275.  
  276.  
  277. #if GDAL_VERSION_MAJOR < 2
  278. if(driver->uses_ogr){
  279. OGRSFDriver *raw = driver->getOGRSFDriver();
  280. OGRDataSource *ds = raw->CreateDataSource(filename.c_str(), options.get());
  281.  
  282. if (!ds) {
  283. Nan::ThrowError("Error creating dataset");
  284. return;
  285. }
  286.  
  287. info.GetReturnValue().Set(Dataset::New(ds));
  288. return;
  289. }
  290. #endif
  291.  
  292. GDALDriver *raw = driver->getGDALDriver();
  293. GDALDataset* ds = raw->Create(filename.c_str(), x_size, y_size, n_bands, type, options.get());
  294.  
  295. if (!ds) {
  296. Nan::ThrowError("Error creating dataset");
  297. return;
  298. }
  299.  
  300. info.GetReturnValue().Set(Dataset::New(ds));
  301. }
  302.  
  303. /**
  304. * Create a copy of a dataset.
  305. *
  306. * @throws Error
  307. * @method createCopy
  308. * @param {String} filename
  309. * @param {gdal.Dataset} src
  310. * @param {Boolean} [strict=false]
  311. * @param {String[]|object} [options=null] An array or object containing driver-specific dataset creation options
  312. * @return gdal.Dataset
  313. */
  314. NAN_METHOD(Driver::createCopy)
  315. {
  316. Nan::HandleScope scope;
  317. Driver *driver = Nan::ObjectWrap::Unwrap<Driver>(info.This());
  318.  
  319. if(!driver->isAlive()){
  320. Nan::ThrowError("Driver object has already been destroyed");
  321. return;
  322. }
  323.  
  324. std::string filename;
  325. Dataset* src_dataset;
  326. unsigned int strict = 0;
  327. StringList options;
  328.  
  329. NODE_ARG_STR(0, "filename", filename);
  330.  
  331. //NODE_ARG_STR(1, "source dataset", src_dataset)
  332. if(info.Length() < 2){
  333. Nan::ThrowError("source dataset must be provided");
  334. return;
  335. }
  336. if (IS_WRAPPED(info[1], Dataset)) {
  337. src_dataset = Nan::ObjectWrap::Unwrap<Dataset>(info[1].As<Object>());
  338. } else {
  339. Nan::ThrowError("source dataset must be a Dataset object");
  340. return;
  341. }
  342.  
  343. if(!src_dataset->isAlive()){
  344. Nan::ThrowError("Dataset object has already been destroyed");
  345. return;
  346. }
  347.  
  348. if(info.Length() > 2 && options.parse(info[2])){
  349. return; //error parsing string list
  350. }
  351.  
  352. #if GDAL_VERSION_MAJOR < 2
  353. if (driver->uses_ogr != src_dataset->uses_ogr){
  354. Nan::ThrowError("Driver unable to copy dataset");
  355. return;
  356. }
  357. if (driver->uses_ogr) {
  358. OGRSFDriver *raw = driver->getOGRSFDriver();
  359. OGRDataSource *raw_ds = src_dataset->getDatasource();
  360.  
  361. OGRDataSource *ds = raw->CopyDataSource(raw_ds, filename.c_str(), options.get());
  362.  
  363. if (!ds) {
  364. Nan::ThrowError("Error copying dataset.");
  365. return;
  366. }
  367.  
  368. info.GetReturnValue().Set(Dataset::New(ds));
  369. return;
  370. }
  371. #endif
  372.  
  373. GDALDriver *raw = driver->getGDALDriver();
  374. GDALDataset *raw_ds = src_dataset->getDataset();
  375. GDALDataset *ds = raw->CreateCopy(filename.c_str(), raw_ds, strict, options.get(), NULL, NULL);
  376.  
  377. if (!ds) {
  378. Nan::ThrowError("Error copying dataset");
  379. return;
  380. }
  381.  
  382. info.GetReturnValue().Set(Dataset::New(ds));
  383. }
  384.  
  385. /**
  386. * Copy the files of a dataset.
  387. *
  388. * @throws Error
  389. * @method copyFiles
  390. * @param {String} name_old New name for the dataset.
  391. * @param {String} name_new Old name of the dataset.
  392. */
  393. NAN_METHOD(Driver::copyFiles)
  394. {
  395. Nan::HandleScope scope;
  396. Driver *driver = Nan::ObjectWrap::Unwrap<Driver>(info.This());
  397. std::string old_name;
  398. std::string new_name;
  399.  
  400. #if GDAL_VERSION_MAJOR < 2
  401. if(driver->uses_ogr) {
  402. Nan::ThrowError("Driver unable to copy files");
  403. return;
  404. }
  405. #endif
  406.  
  407. NODE_ARG_STR(0, "new name", new_name);
  408. NODE_ARG_STR(1, "old name", old_name);
  409.  
  410. CPLErr err = driver->getGDALDriver()->CopyFiles(new_name.c_str(), old_name.c_str());
  411. if (err) {
  412. NODE_THROW_CPLERR(err);
  413. return;
  414. }
  415.  
  416. return;
  417. }
  418.  
  419. /**
  420. * Renames the dataset.
  421. *
  422. * @throws Error
  423. * @method rename
  424. * @param {String} new_name New name for the dataset.
  425. * @param {String} old_name Old name of the dataset.
  426. */
  427. NAN_METHOD(Driver::rename)
  428. {
  429. Nan::HandleScope scope;
  430. Driver *driver = Nan::ObjectWrap::Unwrap<Driver>(info.This());
  431. std::string old_name;
  432. std::string new_name;
  433.  
  434. #if GDAL_VERSION_MAJOR < 2
  435. if(driver->uses_ogr) {
  436. Nan::ThrowError("Driver unable to rename files");
  437. return;
  438. }
  439. #endif
  440.  
  441. NODE_ARG_STR(0, "new name", new_name);
  442. NODE_ARG_STR(1, "old name", old_name);
  443.  
  444. CPLErr err = driver->getGDALDriver()->Rename(new_name.c_str(), old_name.c_str());
  445. if (err) {
  446. NODE_THROW_CPLERR(err);
  447. return;
  448. }
  449.  
  450. return;
  451. }
  452.  
  453. /**
  454. * Returns metadata about the driver.
  455. *
  456. * @throws Error
  457. * @method getMetadata
  458. * @param {String} [domain]
  459. * @return Object
  460. */
  461. NAN_METHOD(Driver::getMetadata)
  462. {
  463. Nan::HandleScope scope;
  464. Driver *driver = Nan::ObjectWrap::Unwrap<Driver>(info.This());
  465.  
  466. Local<Object> result;
  467.  
  468. std::string domain("");
  469. NODE_ARG_OPT_STR(0, "domain", domain);
  470.  
  471. #if GDAL_VERSION_MAJOR < 2
  472. if (driver->uses_ogr){
  473. result = Nan::New<Object>();
  474. Nan::Set(result, Nan::New("DCAP_VECTOR").ToLocalChecked(), Nan::New("YES").ToLocalChecked());
  475. info.GetReturnValue().Set(result);
  476. return;
  477. }
  478. #endif
  479.  
  480. GDALDriver* raw = driver->getGDALDriver();
  481. result = MajorObject::getMetadata(raw, domain.empty() ? NULL : domain.c_str());
  482. #if GDAL_VERSION_MAJOR < 2
  483. Nan::Set(result, Nan::New("DCAP_RASTER").ToLocalChecked(), Nan::New("YES").ToLocalChecked());
  484. #endif
  485. info.GetReturnValue().Set(result);
  486. }
  487.  
  488. /**
  489. * Opens a dataset.
  490. *
  491. * @throws Error
  492. * @method open
  493. * @param {String} path
  494. * @param {String} [mode=`"r"`] The mode to use to open the file: `"r"` or `"r+"`
  495. * @return {gdal.Dataset}
  496. */
  497. NAN_METHOD(Driver::open)
  498. {
  499. Nan::HandleScope scope;
  500. Driver *driver = Nan::ObjectWrap::Unwrap<Driver>(info.This());
  501.  
  502. std::string path;
  503. std::string mode = "r";
  504. GDALAccess access = GA_ReadOnly;
  505.  
  506. NODE_ARG_STR(0, "path", path);
  507. NODE_ARG_OPT_STR(1, "mode", mode);
  508.  
  509. if (mode == "r+") {
  510. access = GA_Update;
  511. } else if (mode != "r") {
  512. Nan::ThrowError("Invalid open mode. Must be \"r\" or \"r+\"");
  513. return;
  514. }
  515.  
  516. #if GDAL_VERSION_MAJOR < 2
  517. if (driver->uses_ogr){
  518. OGRSFDriver *raw = driver->getOGRSFDriver();
  519. OGRDataSource *ds = raw->Open(path.c_str(), static_cast<int>(access));
  520. if (!ds) {
  521. Nan::ThrowError("Error opening dataset");
  522. return;
  523. }
  524. info.GetReturnValue().Set(Dataset::New(ds));
  525. return;
  526. }
  527. #endif
  528.  
  529. GDALDriver *raw = driver->getGDALDriver();
  530. GDALOpenInfo *open_info = new GDALOpenInfo(path.c_str(), access);
  531. GDALDataset *ds = raw->pfnOpen(open_info);
  532. delete open_info;
  533. if (!ds) {
  534. Nan::ThrowError("Error opening dataset");
  535. return;
  536. }
  537. info.GetReturnValue().Set(Dataset::New(ds));
  538. }
  539.  
  540. } // namespace node_gdal
  541.